@lievclouds/dsh-cortex 0.4.4 → 1.0.0

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.

Potentially problematic release.


This version of @lievclouds/dsh-cortex might be problematic. Click here for more details.

Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/client.js +428 -406
  3. package/index.js +7 -0
  4. package/locale/en.json +6 -6
  5. package/locale/zh.json +6 -6
  6. package/package.json +115 -106
  7. package/src/cortex-ui/dsh/api.ts +5 -2
  8. package/src/cortex-ui/dsh/css-overrides.css +8 -0
  9. package/src/cortex-ui/renderer/App.tsx +39 -0
  10. package/src/cortex-ui/renderer/components/asset/AssetDetail.tsx +9 -1
  11. package/src/cortex-ui/renderer/components/miniapp/FileTree.tsx +161 -0
  12. package/src/cortex-ui/renderer/components/miniapp/MiniappCard.tsx +263 -0
  13. package/src/cortex-ui/renderer/components/miniapp/MiniappDetail.tsx +1493 -0
  14. package/src/cortex-ui/renderer/components/retest/CurlImportDialog.tsx +158 -0
  15. package/src/cortex-ui/renderer/components/retest/RepeaterCollectionsDialog.tsx +327 -0
  16. package/src/cortex-ui/renderer/components/retest/RepeaterHistoryDialog.tsx +242 -0
  17. package/src/cortex-ui/renderer/components/retest/RepeaterPanel.tsx +333 -148
  18. package/src/cortex-ui/renderer/components/retest/YakitSendPanel.tsx +411 -0
  19. package/src/cortex-ui/renderer/components/vuln/DirectoryPickerDialog.tsx +187 -0
  20. package/src/cortex-ui/renderer/components/vuln/ExportReportDialog.tsx +173 -59
  21. package/src/cortex-ui/renderer/components/vuln/VulnDetail.tsx +16 -4
  22. package/src/cortex-ui/renderer/i18n/messages/common.ts +2 -0
  23. package/src/cortex-ui/renderer/i18n/messages/fuzzer.ts +32 -0
  24. package/src/cortex-ui/renderer/i18n/messages/index.ts +5 -1
  25. package/src/cortex-ui/renderer/i18n/messages/miniapp.ts +392 -0
  26. package/src/cortex-ui/renderer/i18n/messages/retest.ts +146 -2
  27. package/src/cortex-ui/renderer/i18n/messages/vuln.ts +26 -6
  28. package/src/cortex-ui/renderer/lib/curl.ts +635 -0
  29. package/src/cortex-ui/renderer/lib/miniappApi.ts +459 -0
  30. package/src/cortex-ui/renderer/lib/navigation.ts +13 -1
  31. package/src/cortex-ui/renderer/lib/repeaterRaw.ts +102 -0
  32. package/src/cortex-ui/renderer/lib/repeaterStoreApi.ts +163 -0
  33. package/src/cortex-ui/renderer/lib/retestResponse.ts +64 -0
  34. package/src/cortex-ui/renderer/lib/transport/httpClient.ts +1 -1
  35. package/src/cortex-ui/renderer/pages/DashboardPage.tsx +3 -3
  36. package/src/cortex-ui/renderer/pages/FuzzerPage.tsx +212 -0
  37. package/src/cortex-ui/renderer/pages/MiniappPage.tsx +664 -0
  38. package/src/cortex-ui/shared/ipc.ts +3 -4
  39. package/src/cortex-ui/shared/types.ts +9 -0
  40. package/src/host/cortex/fs.js +72 -0
  41. package/src/host/cortex/index.js +49 -1
  42. package/src/host/cortex/repeater-store.js +411 -0
  43. package/src/host/cortex/repeater.js +15 -2
  44. package/src/host/cortex/settings.js +54 -0
  45. package/src/host/cortex/tools.js +2 -0
  46. package/src/host/cortex/vulns.js +36 -13
  47. package/src/host/miniapp/analyze.js +1078 -0
  48. package/src/host/miniapp/assets-import.js +294 -0
  49. package/src/host/miniapp/detect.js +426 -0
  50. package/src/host/miniapp/format.js +263 -0
  51. package/src/host/miniapp/roots.js +360 -0
  52. package/src/host/miniapp/routes.js +304 -0
  53. package/src/host/miniapp/service.js +559 -0
  54. package/src/host/miniapp/store.js +756 -0
  55. package/src/host/miniapp/tools.js +335 -0
  56. package/src/host/miniapp/unpack.js +1010 -0
  57. package/src/host/miniapp/wxapkg.js +416 -0
  58. package/src/host/reports-office.js +341 -0
@@ -0,0 +1,392 @@
1
+ import type { MessageBundle } from './types'
2
+
3
+ /**
4
+ * Mini-program reverse engineering (wxapkg) UI copy.
5
+ *
6
+ * Everything the page renders lives here so the vendored renderer keeps its
7
+ * "no user-facing literals in TSX" rule. Data values (appid, package paths,
8
+ * extracted hosts) are interpolated by the caller and intentionally stay
9
+ * untranslated.
10
+ */
11
+ export const miniappMessages: MessageBundle = {
12
+ zh: {
13
+ // Nav + page chrome
14
+ 'nav.miniapps': '小程序逆向',
15
+ 'miniapp.page.eyebrow': 'MINI PROGRAM',
16
+ 'miniapp.page.count': '{count} 个包 · {apps} 个应用',
17
+ 'miniapp.page.countVisible': '显示 {visible} / 共 {total} 个包 · {apps} 个应用',
18
+ 'miniapp.page.hiddenExtras': '已默认折叠 {count} 个插件/公共库包',
19
+ 'miniapp.page.rootsSummary': '扫描范围:{summary}',
20
+ 'miniapp.page.loading': '正在加载小程序包…',
21
+
22
+ // Authorization banner
23
+ 'miniapp.banner.title': '仅处理已授权的小程序包',
24
+ 'miniapp.banner.workspace': '解包工作区:{path}',
25
+ 'miniapp.banner.roots': '自定义目录 {count} 个',
26
+
27
+ // Toolbar
28
+ 'miniapp.action.scan': '扫描本机',
29
+ 'miniapp.action.scanning': '扫描中…',
30
+ 'miniapp.action.addRoot': '添加自定义目录',
31
+ 'miniapp.action.addRootSubmit': '添加并扫描',
32
+ 'miniapp.action.addRootCancel': '取消',
33
+ 'miniapp.addRoot.placeholder': '例如 C:\\mini-programs',
34
+ 'miniapp.addRoot.hint': '自定义目录会持久化到本机设置,仅扫描其中的 .wxapkg 文件。',
35
+ 'miniapp.search.placeholder': '搜索 appid、应用名或包路径',
36
+ 'miniapp.search.ariaLabel': '搜索小程序包',
37
+ 'miniapp.search.clear': '清除搜索',
38
+ 'miniapp.filter.statusAria': '按状态筛选小程序包',
39
+ 'miniapp.filter.all': '全部状态',
40
+ 'miniapp.scan.done': '{total} 个包 · {added} 新增 · {updated} 更新 · {unchanged} 未变',
41
+ 'miniapp.scan.failed': '扫描失败:{error}',
42
+ 'miniapp.scan.errors': '{count} 个路径读取失败',
43
+ 'miniapp.toast.rootAdded': '已添加自定义目录:{path}',
44
+ 'miniapp.toast.rootFailed': '添加目录失败:{error}',
45
+
46
+ // List states
47
+ 'miniapp.error.title': '无法加载小程序包列表',
48
+ 'miniapp.empty.title': '还没有扫描到小程序包',
49
+ 'miniapp.empty.description':
50
+ '扫描本机微信缓存中的 .wxapkg 包,或添加一个自定义目录,解包后即可浏览源码并提取接口、域名与敏感信息。',
51
+ 'miniapp.empty.cta': '扫描本机',
52
+ 'miniapp.emptyFiltered.title': '没有符合条件的小程序包',
53
+ 'miniapp.emptyFiltered.description': '换一个关键词或状态筛选试试。',
54
+ 'miniapp.emptyFiltered.reset': '重置筛选',
55
+
56
+ // Status / format badges
57
+ 'miniapp.status.detected': '已检测',
58
+ 'miniapp.status.decrypting': '解密中',
59
+ 'miniapp.status.unpacked': '已解包',
60
+ 'miniapp.status.unsupported': '不支持',
61
+ 'miniapp.status.failed': '失败',
62
+ 'miniapp.format.plain': '明文',
63
+ 'miniapp.format.v1mmwx': 'V1MMWX',
64
+ 'miniapp.format.unknown': '未知',
65
+
66
+ // Source card
67
+ 'miniapp.card.version': 'v{version}',
68
+ 'miniapp.card.noVersion': '无版本',
69
+ 'miniapp.card.versions': '{count} 个版本',
70
+ 'miniapp.card.files': '{count} 个文件',
71
+ 'miniapp.card.updated': '更新于 {time}',
72
+ 'miniapp.card.errorLabel': '错误:{error}',
73
+ 'miniapp.card.unsupportedLabel': '暂不支持:{error}',
74
+ 'miniapp.card.copies': '{count} 份缓存副本',
75
+ 'miniapp.kind.app': '小程序',
76
+ 'miniapp.kind.plugin': '微信插件',
77
+ 'miniapp.kind.library': '微信公共库',
78
+ 'miniapp.kind.unknown': '未识别包',
79
+ 'miniapp.unnamed': '未命名小程序',
80
+ 'miniapp.filter.showExtras': '显示插件/公共库包',
81
+ 'miniapp.filter.hideExtras': '隐藏插件/公共库包',
82
+ 'miniapp.emptyExtras.title': '只有插件/公共库包',
83
+ 'miniapp.emptyExtras.description': '插件和公共库包通常没有独立中文名,勾选“显示插件/公共库包”后查看。',
84
+ 'miniapp.emptyExtras.cta': '显示插件/公共库包',
85
+ 'miniapp.action.unpack': '解包',
86
+ 'miniapp.action.unpacking': '解包中…',
87
+ 'miniapp.action.browse': '浏览文件',
88
+ 'miniapp.action.analyze': '生成摘要',
89
+ 'miniapp.action.analyzing': '分析中…',
90
+ 'miniapp.action.import': '导入资产',
91
+ 'miniapp.action.importing': '导入中…',
92
+ 'miniapp.action.openDir': '打开目录',
93
+ 'miniapp.action.opening': '打开中…',
94
+
95
+ // Action toasts
96
+ 'miniapp.toast.unpacked': '已解包 {appid}',
97
+ 'miniapp.toast.unpackUnsupported': '无法解包:{error}',
98
+ 'miniapp.toast.unpackFailed': '解包失败:{error}',
99
+ 'miniapp.toast.analyzed':
100
+ '摘要已生成:{pages} 个页面 · {endpoints} 个接口 · {secrets} 条敏感信息',
101
+ 'miniapp.toast.analyzeFailed': '生成摘要失败:{error}',
102
+ 'miniapp.toast.imported':
103
+ '已导入 {assets} 个资产、{interfaces} 个接口、{leaks} 条泄露信息、{parameters} 个参数',
104
+ 'miniapp.toast.importWarnings': '导入未创建资产:{warnings}',
105
+ 'miniapp.toast.importFailed': '导入资产失败:{error}',
106
+ 'miniapp.toast.opened': '已打开目录:{path}',
107
+ 'miniapp.toast.openFailed': '打开目录失败:{error}',
108
+
109
+ // Detail sheet
110
+ 'miniapp.detail.eyebrow': 'MINI PROGRAM SOURCE',
111
+ 'miniapp.detail.loading': '正在加载小程序详情…',
112
+ 'miniapp.detail.loadError': '无法读取小程序详情',
113
+ 'miniapp.detail.tab.overview': '概览',
114
+ 'miniapp.detail.tab.files': '文件',
115
+ 'miniapp.detail.tab.search': '搜索',
116
+ 'miniapp.detail.copySummary': '复制摘要',
117
+ 'miniapp.detail.copiedSummary': '已复制小程序摘要',
118
+ 'miniapp.detail.noSummary': '尚未生成摘要,请先点击“生成摘要”。',
119
+ 'miniapp.detail.generate': '生成摘要',
120
+ 'miniapp.detail.rename': '重命名小程序',
121
+ 'miniapp.detail.renamePlaceholder': '输入显示名称,例如中文名',
122
+ 'miniapp.detail.renameSave': '保存名称',
123
+ 'miniapp.detail.renamed': '显示名称已更新',
124
+ 'miniapp.detail.renameFailed': '重命名失败:{error}',
125
+ 'miniapp.detail.generating': '分析中…',
126
+ 'miniapp.detail.importAssets': '导入资产',
127
+ 'miniapp.detail.importing': '导入中…',
128
+
129
+ // Detail overview
130
+ 'miniapp.detail.count.pages': '页面',
131
+ 'miniapp.detail.count.subPackages': '分包',
132
+ 'miniapp.detail.count.domains': '域名',
133
+ 'miniapp.detail.count.endpoints': '接口',
134
+ 'miniapp.detail.count.secrets': '敏感信息',
135
+ 'miniapp.detail.count.parameters': '参数',
136
+ 'miniapp.detail.extracted.heading': '提取结果',
137
+ 'miniapp.detail.extracted.hint': '点击分类查看,点击条目可在文件页定位源码',
138
+ 'miniapp.detail.extracted.open': '查看源码',
139
+ 'miniapp.detail.extracted.empty': '暂无数据',
140
+ 'miniapp.detail.extracted.subPages': '{count} 个页面',
141
+ 'miniapp.detail.extracted.hits': '{count} 次命中',
142
+ 'miniapp.detail.overview.heading': '概览',
143
+ 'miniapp.detail.overview.filesSummary': '{text} 个文本文件 / {binary} 个二进制文件 · {size}',
144
+ 'miniapp.detail.overview.largestFiles': '最大文件',
145
+ 'miniapp.detail.overview.warnings': '警告',
146
+ 'miniapp.detail.overview.versions': '历史版本',
147
+ 'miniapp.detail.overview.analysisMissing': '还没有生成摘要',
148
+ 'miniapp.detail.overview.analysisMissingHint':
149
+ '生成摘要后,这里会显示页面、分包、域名、接口、敏感信息与参数统计。',
150
+ 'miniapp.detail.versionMeta': '{status} · {format} · {size} · {files} 个文件 · {time}',
151
+ 'miniapp.detail.meta.rootKind': '来源',
152
+ 'miniapp.detail.meta.packageDir': '包目录',
153
+ 'miniapp.detail.meta.unpackedPath': '解包目录',
154
+ 'miniapp.detail.meta.format': '格式',
155
+ 'miniapp.detail.meta.updated': '更新时间',
156
+ 'miniapp.detail.importResult.title': '资产导入结果',
157
+ 'miniapp.detail.importResult.totals':
158
+ '资产 {assets} · 接口 {interfaces} · 泄露 {leaks} · 参数 {parameters}',
159
+ 'miniapp.detail.importResult.project': '项目:{project}',
160
+ 'miniapp.detail.importResult.warnings': '警告:{warnings}',
161
+
162
+ // Files tab
163
+ 'miniapp.file.loading': '正在读取…',
164
+ 'miniapp.file.empty': '该目录为空',
165
+ 'miniapp.file.selectPrompt': '从左侧文件树选择一个文件查看文本内容。',
166
+ 'miniapp.file.previewTitle': '文件预览',
167
+ 'miniapp.file.formatted': '已格式化',
168
+ 'miniapp.file.findPlaceholder': '在文件中搜索',
169
+ 'miniapp.file.findSubmit': '查找',
170
+ 'miniapp.file.findPrev': '上一个匹配',
171
+ 'miniapp.file.findNext': '下一个匹配',
172
+ 'miniapp.file.findNone': '无匹配',
173
+ 'miniapp.file.findRegex': '使用正则',
174
+ 'miniapp.file.binary': '二进制文件,无法以文本预览。',
175
+ 'miniapp.file.truncated': '内容已截断,仅显示前 {lines} 行。',
176
+ 'miniapp.file.loadedProgress': '已加载 {loaded} / {total} 行 · 滚动到底部自动加载',
177
+ 'miniapp.file.allLoaded': '已加载全部 {total} 行',
178
+ 'miniapp.file.sourceTruncated': '文件超过 5MB,仅加载前 5MB(预览受限)',
179
+ 'miniapp.file.loadMore': '加载更多',
180
+ 'miniapp.file.loadError': '读取文件失败:{error}',
181
+ 'miniapp.file.treeError': '读取目录失败:{error}',
182
+ 'miniapp.file.root': '根目录',
183
+ 'miniapp.file.totalLines': '共 {count} 行',
184
+
185
+ // Search tab
186
+ 'miniapp.search.queryPlaceholder': '搜索源码关键词',
187
+ 'miniapp.search.queryAria': '搜索源码关键词',
188
+ 'miniapp.search.regex': '正则',
189
+ 'miniapp.search.glob': 'Glob',
190
+ 'miniapp.search.globPlaceholder': '例如 pages/**/*.js',
191
+ 'miniapp.search.maxResults': '上限',
192
+ 'miniapp.search.submit': '搜索',
193
+ 'miniapp.search.searching': '搜索中…',
194
+ 'miniapp.search.empty': '输入关键词后搜索已解包的源码。',
195
+ 'miniapp.search.noResults': '没有匹配结果。',
196
+ 'miniapp.search.summary': '{count} 条匹配 · 扫描 {scanned} 个文件',
197
+ 'miniapp.search.truncated': '结果已截断,请缩小范围。',
198
+ 'miniapp.search.error': '搜索失败:{error}',
199
+ 'miniapp.search.resultAria': '预览 {file}:{line}'
200
+ },
201
+ en: {
202
+ // Nav + page chrome
203
+ 'nav.miniapps': 'Mini Programs',
204
+ 'miniapp.page.eyebrow': 'MINI PROGRAM',
205
+ 'miniapp.page.count': '{count} packages · {apps} apps',
206
+ 'miniapp.page.countVisible': 'Showing {visible} of {total} packages · {apps} apps',
207
+ 'miniapp.page.hiddenExtras': '{count} plugin/public-library packages folded by default',
208
+ 'miniapp.page.rootsSummary': 'Scan roots: {summary}',
209
+ 'miniapp.page.loading': 'Loading mini-program packages…',
210
+
211
+ // Authorization banner
212
+ 'miniapp.banner.title': 'Authorized mini-program packages only',
213
+ 'miniapp.banner.workspace': 'Unpack workspace: {path}',
214
+ 'miniapp.banner.roots': '{count} custom directories',
215
+
216
+ // Toolbar
217
+ 'miniapp.action.scan': 'Scan this machine',
218
+ 'miniapp.action.scanning': 'Scanning…',
219
+ 'miniapp.action.addRoot': 'Add custom directory',
220
+ 'miniapp.action.addRootSubmit': 'Add and scan',
221
+ 'miniapp.action.addRootCancel': 'Cancel',
222
+ 'miniapp.addRoot.placeholder': 'e.g. C:\\mini-programs',
223
+ 'miniapp.addRoot.hint':
224
+ 'Custom directories are stored in local settings and only scanned for .wxapkg files.',
225
+ 'miniapp.search.placeholder': 'Search appid, app name or package path',
226
+ 'miniapp.search.ariaLabel': 'Search mini-program packages',
227
+ 'miniapp.search.clear': 'Clear search',
228
+ 'miniapp.filter.statusAria': 'Filter mini-program packages by status',
229
+ 'miniapp.filter.all': 'All statuses',
230
+ 'miniapp.scan.done': '{total} packages · {added} added · {updated} updated · {unchanged} unchanged',
231
+ 'miniapp.scan.failed': 'Scan failed: {error}',
232
+ 'miniapp.scan.errors': '{count} paths could not be read',
233
+ 'miniapp.toast.rootAdded': 'Custom directory added: {path}',
234
+ 'miniapp.toast.rootFailed': 'Failed to add directory: {error}',
235
+
236
+ // List states
237
+ 'miniapp.error.title': 'Unable to load mini-program packages',
238
+ 'miniapp.empty.title': 'No mini-program packages found yet',
239
+ 'miniapp.empty.description':
240
+ 'Scan the .wxapkg packages in local WeChat caches, or add a custom directory. Once unpacked, browse source and extract endpoints, domains and secrets.',
241
+ 'miniapp.empty.cta': 'Scan this machine',
242
+ 'miniapp.emptyFiltered.title': 'No matching mini-program packages',
243
+ 'miniapp.emptyFiltered.description': 'Try a different keyword or status filter.',
244
+ 'miniapp.emptyFiltered.reset': 'Reset filters',
245
+
246
+ // Status / format badges
247
+ 'miniapp.status.detected': 'Detected',
248
+ 'miniapp.status.decrypting': 'Decrypting',
249
+ 'miniapp.status.unpacked': 'Unpacked',
250
+ 'miniapp.status.unsupported': 'Unsupported',
251
+ 'miniapp.status.failed': 'Failed',
252
+ 'miniapp.format.plain': 'Plain',
253
+ 'miniapp.format.v1mmwx': 'V1MMWX',
254
+ 'miniapp.format.unknown': 'Unknown',
255
+
256
+ // Source card
257
+ 'miniapp.card.version': 'v{version}',
258
+ 'miniapp.card.noVersion': 'No version',
259
+ 'miniapp.card.versions': '{count} versions',
260
+ 'miniapp.card.files': '{count} files',
261
+ 'miniapp.card.updated': 'Updated {time}',
262
+ 'miniapp.card.errorLabel': 'Error: {error}',
263
+ 'miniapp.card.unsupportedLabel': 'Not supported: {error}',
264
+ 'miniapp.card.copies': '{count} cached copies',
265
+ 'miniapp.kind.app': 'Mini program',
266
+ 'miniapp.kind.plugin': 'WeChat plugin',
267
+ 'miniapp.kind.library': 'WeChat public library',
268
+ 'miniapp.kind.unknown': 'Unknown package',
269
+ 'miniapp.unnamed': 'Unnamed mini program',
270
+ 'miniapp.filter.showExtras': 'Show plugins/public libraries',
271
+ 'miniapp.filter.hideExtras': 'Hide plugins/public libraries',
272
+ 'miniapp.emptyExtras.title': 'Only plugin/public-library packages',
273
+ 'miniapp.emptyExtras.description':
274
+ 'Plugin and public-library packages usually have no standalone Chinese name. Enable “Show plugins/public libraries” to inspect them.',
275
+ 'miniapp.emptyExtras.cta': 'Show plugins/public libraries',
276
+ 'miniapp.action.unpack': 'Unpack',
277
+ 'miniapp.action.unpacking': 'Unpacking…',
278
+ 'miniapp.action.browse': 'Browse files',
279
+ 'miniapp.action.analyze': 'Generate summary',
280
+ 'miniapp.action.analyzing': 'Analyzing…',
281
+ 'miniapp.action.import': 'Import assets',
282
+ 'miniapp.action.importing': 'Importing…',
283
+ 'miniapp.action.openDir': 'Open directory',
284
+ 'miniapp.action.opening': 'Opening…',
285
+
286
+ // Action toasts
287
+ 'miniapp.toast.unpacked': 'Unpacked {appid}',
288
+ 'miniapp.toast.unpackUnsupported': 'Cannot unpack: {error}',
289
+ 'miniapp.toast.unpackFailed': 'Unpack failed: {error}',
290
+ 'miniapp.toast.analyzed':
291
+ 'Summary generated: {pages} pages · {endpoints} endpoints · {secrets} secrets',
292
+ 'miniapp.toast.analyzeFailed': 'Summary failed: {error}',
293
+ 'miniapp.toast.imported':
294
+ 'Imported {assets} assets, {interfaces} interfaces, {leaks} leaks, {parameters} parameters',
295
+ 'miniapp.toast.importWarnings': 'No asset was created: {warnings}',
296
+ 'miniapp.toast.importFailed': 'Asset import failed: {error}',
297
+ 'miniapp.toast.opened': 'Opened directory: {path}',
298
+ 'miniapp.toast.openFailed': 'Failed to open directory: {error}',
299
+
300
+ // Detail sheet
301
+ 'miniapp.detail.eyebrow': 'MINI PROGRAM SOURCE',
302
+ 'miniapp.detail.loading': 'Loading mini-program details…',
303
+ 'miniapp.detail.loadError': 'Unable to load mini-program details',
304
+ 'miniapp.detail.tab.overview': 'Overview',
305
+ 'miniapp.detail.tab.files': 'Files',
306
+ 'miniapp.detail.tab.search': 'Search',
307
+ 'miniapp.detail.copySummary': 'Copy summary',
308
+ 'miniapp.detail.copiedSummary': 'Mini-program summary copied',
309
+ 'miniapp.detail.noSummary': 'No summary yet. Generate one first.',
310
+ 'miniapp.detail.generate': 'Generate summary',
311
+ 'miniapp.detail.rename': 'Rename mini program',
312
+ 'miniapp.detail.renamePlaceholder': 'Display name, e.g. the Chinese name',
313
+ 'miniapp.detail.renameSave': 'Save display name',
314
+ 'miniapp.detail.renamed': 'Display name updated',
315
+ 'miniapp.detail.renameFailed': 'Rename failed: {error}',
316
+ 'miniapp.detail.generating': 'Analyzing…',
317
+ 'miniapp.detail.importAssets': 'Import assets',
318
+ 'miniapp.detail.importing': 'Importing…',
319
+
320
+ // Detail overview
321
+ 'miniapp.detail.count.pages': 'Pages',
322
+ 'miniapp.detail.count.subPackages': 'Subpackages',
323
+ 'miniapp.detail.count.domains': 'Domains',
324
+ 'miniapp.detail.count.endpoints': 'Endpoints',
325
+ 'miniapp.detail.count.secrets': 'Secrets',
326
+ 'miniapp.detail.count.parameters': 'Parameters',
327
+ 'miniapp.detail.extracted.heading': 'Extracted data',
328
+ 'miniapp.detail.extracted.hint': 'Pick a category; click a row to locate its source',
329
+ 'miniapp.detail.extracted.open': 'View source',
330
+ 'miniapp.detail.extracted.empty': 'Nothing extracted',
331
+ 'miniapp.detail.extracted.subPages': '{count} pages',
332
+ 'miniapp.detail.extracted.hits': '{count} hits',
333
+ 'miniapp.detail.overview.heading': 'Overview',
334
+ 'miniapp.detail.overview.filesSummary': '{text} text files / {binary} binary files · {size}',
335
+ 'miniapp.detail.overview.largestFiles': 'Largest files',
336
+ 'miniapp.detail.overview.warnings': 'Warnings',
337
+ 'miniapp.detail.overview.versions': 'Versions',
338
+ 'miniapp.detail.overview.analysisMissing': 'No summary generated',
339
+ 'miniapp.detail.overview.analysisMissingHint':
340
+ 'Generate a summary to see pages, subpackages, domains, endpoints, secrets and parameter counts.',
341
+ 'miniapp.detail.versionMeta': '{status} · {format} · {size} · {files} files · {time}',
342
+ 'miniapp.detail.meta.rootKind': 'Source',
343
+ 'miniapp.detail.meta.packageDir': 'Package directory',
344
+ 'miniapp.detail.meta.unpackedPath': 'Unpacked directory',
345
+ 'miniapp.detail.meta.format': 'Format',
346
+ 'miniapp.detail.meta.updated': 'Updated',
347
+ 'miniapp.detail.importResult.title': 'Asset import result',
348
+ 'miniapp.detail.importResult.totals':
349
+ 'Assets {assets} · Interfaces {interfaces} · Leaks {leaks} · Parameters {parameters}',
350
+ 'miniapp.detail.importResult.project': 'Project: {project}',
351
+ 'miniapp.detail.importResult.warnings': 'Warnings: {warnings}',
352
+
353
+ // Files tab
354
+ 'miniapp.file.loading': 'Loading…',
355
+ 'miniapp.file.empty': 'This directory is empty',
356
+ 'miniapp.file.selectPrompt': 'Pick a file from the tree to preview its text.',
357
+ 'miniapp.file.previewTitle': 'File preview',
358
+ 'miniapp.file.formatted': 'Formatted',
359
+ 'miniapp.file.findPlaceholder': 'Find in file',
360
+ 'miniapp.file.findSubmit': 'Find',
361
+ 'miniapp.file.findPrev': 'Previous match',
362
+ 'miniapp.file.findNext': 'Next match',
363
+ 'miniapp.file.findNone': 'No matches',
364
+ 'miniapp.file.findRegex': 'Use regex',
365
+ 'miniapp.file.binary': 'Binary file; text preview is unavailable.',
366
+ 'miniapp.file.truncated': 'Content truncated to the first {lines} lines.',
367
+ 'miniapp.file.loadedProgress': '{loaded} of {total} lines loaded · scroll to load more',
368
+ 'miniapp.file.allLoaded': 'All {total} lines loaded',
369
+ 'miniapp.file.sourceTruncated': 'File exceeds 5 MB; only the first 5 MB is previewed',
370
+ 'miniapp.file.loadMore': 'Load more',
371
+ 'miniapp.file.loadError': 'Failed to read file: {error}',
372
+ 'miniapp.file.treeError': 'Failed to read directory: {error}',
373
+ 'miniapp.file.root': 'Root',
374
+ 'miniapp.file.totalLines': '{count} lines',
375
+
376
+ // Search tab
377
+ 'miniapp.search.queryPlaceholder': 'Search source text',
378
+ 'miniapp.search.queryAria': 'Search source keywords',
379
+ 'miniapp.search.regex': 'Regex',
380
+ 'miniapp.search.glob': 'Glob',
381
+ 'miniapp.search.globPlaceholder': 'e.g. pages/**/*.js',
382
+ 'miniapp.search.maxResults': 'Limit',
383
+ 'miniapp.search.submit': 'Search',
384
+ 'miniapp.search.searching': 'Searching…',
385
+ 'miniapp.search.empty': 'Enter a keyword to search the unpacked source.',
386
+ 'miniapp.search.noResults': 'No matches.',
387
+ 'miniapp.search.summary': '{count} matches · scanned {scanned} files',
388
+ 'miniapp.search.truncated': 'Results truncated; narrow the query.',
389
+ 'miniapp.search.error': 'Search failed: {error}',
390
+ 'miniapp.search.resultAria': 'Preview {file}:{line}'
391
+ }
392
+ }
@@ -38,6 +38,7 @@ export const retestMessages: MessageBundle = {
38
38
  'retest.repeater.stepN': '步骤{n}',
39
39
  'retest.repeater.followRedirect': '跟随重定向',
40
40
  'retest.repeater.viewRaw': '原始',
41
+ 'retest.repeater.formatJson': '格式化',
41
42
  'retest.repeater.viewHtml': '渲染',
42
43
  'retest.repeater.htmlPreview': 'HTML 渲染预览',
43
44
  'retest.repeater.emptyResponse': '发送请求后显示原始响应',
@@ -454,7 +455,76 @@ export const retestMessages: MessageBundle = {
454
455
  'retest.config.meta.activeProvider': '当前提供商:{label}',
455
456
  'retest.config.meta.noActiveProvider': '未选择当前提供商',
456
457
  'retest.config.meta.providerCount': '{count} 个提供商',
457
- 'retest.config.noProvidersActiveHint': '配置至少一个模型提供商后,才能生成 PoC。'
458
+ 'retest.config.noProvidersActiveHint': '配置至少一个模型提供商后,才能生成 PoC。',
459
+
460
+ // ------------------------------------------------------------------
461
+ // Single-Repeater additions (history / favorites / curl import+export).
462
+ // Appended block; existing keys above are untouched.
463
+ // ------------------------------------------------------------------
464
+ 'retest.repeater.requestSection': '请求',
465
+ 'retest.repeater.formatRequest': '格式化',
466
+ 'retest.repeater.formatRequestTitle': '格式化请求体(JSON)',
467
+ 'retest.repeater.formatRequestFailed': '请求体不是合法的 JSON,无法格式化',
468
+
469
+ // Send history
470
+ 'retest.repeater.history.open': '历史',
471
+ 'retest.repeater.history.title': '发送历史',
472
+ 'retest.repeater.history.description': '最近发送记录;点击一条可同时恢复请求与响应。',
473
+ 'retest.repeater.history.loading': '正在加载发送历史…',
474
+ 'retest.repeater.history.error': '加载发送历史失败:{error}',
475
+ 'retest.repeater.history.empty': '还没有发送记录',
476
+ 'retest.repeater.history.emptyHint': '发送一次请求后,记录会自动保存在本机。',
477
+ 'retest.repeater.history.itemAria': '{method} {url},状态 {status},{time}',
478
+ 'retest.repeater.history.noResponse': '无响应',
479
+ 'retest.repeater.history.restore': '点击恢复',
480
+ 'retest.repeater.history.refresh': '刷新发送历史',
481
+ 'retest.repeater.history.footerHint': '仅保存在本机,最多 50 条',
482
+ 'retest.repeater.history.clear': '清空历史',
483
+ 'retest.repeater.history.cleared': '发送历史已清空',
484
+ 'retest.repeater.history.clearFailed': '清空发送历史失败:{error}',
485
+
486
+ // Favorites
487
+ 'retest.repeater.favorites.open': '收藏',
488
+ 'retest.repeater.favorites.title': '收藏请求',
489
+ 'retest.repeater.favorites.description': '命名保存当前请求,之后可一键恢复请求与响应。',
490
+ 'retest.repeater.favorites.nameLabel': '名称',
491
+ 'retest.repeater.favorites.namePlaceholder': '例如:登录后查询发票',
492
+ 'retest.repeater.favorites.nameInvalid': '名称需为 1–80 个字符',
493
+ 'retest.repeater.favorites.save': '收藏当前请求',
494
+ 'retest.repeater.favorites.saving': '正在保存…',
495
+ 'retest.repeater.favorites.saveHint': '保存原始请求与最近一次响应,名称最多 80 个字符。',
496
+ 'retest.repeater.favorites.invalidRequest':
497
+ '当前编辑器内容无法解析,修正请求行或请求头后才能收藏。',
498
+ 'retest.repeater.favorites.saved': '已收藏当前请求',
499
+ 'retest.repeater.favorites.saveFailed': '收藏失败:{error}',
500
+ 'retest.repeater.favorites.loading': '正在加载收藏…',
501
+ 'retest.repeater.favorites.error': '加载收藏失败:{error}',
502
+ 'retest.repeater.favorites.empty': '还没有收藏的请求',
503
+ 'retest.repeater.favorites.emptyHint': '发送前先收藏,之后可以随时恢复。',
504
+ 'retest.repeater.favorites.loadAria': '加载收藏:{name}',
505
+ 'retest.repeater.favorites.deleteAria': '删除收藏:{name}',
506
+ 'retest.repeater.favorites.deleted': '已删除收藏',
507
+ 'retest.repeater.favorites.deleteFailed': '删除收藏失败:{error}',
508
+ 'retest.repeater.favorites.footerHint': '仅保存在本机,最多 50 条',
509
+
510
+ // curl import / export
511
+ 'retest.repeater.curl.import': '导入 curl',
512
+ 'retest.repeater.curl.export': '导出 curl',
513
+ 'retest.repeater.curl.exported': '已复制 curl 命令',
514
+ 'retest.repeater.curl.parseFailed': '当前请求无法解析,无法导出 curl',
515
+ 'retest.repeater.curl.importTitle': '导入 curl 命令',
516
+ 'retest.repeater.curl.importDescription':
517
+ '支持 bash/zsh 与 Windows cmd 风格;解析结果会替换编辑器中的原始请求。',
518
+ 'retest.repeater.curl.inputLabel': 'curl 命令',
519
+ 'retest.repeater.curl.inputPlaceholder':
520
+ "curl 'https://example.com/api' -H 'Accept: application/json' -d 'a=1'",
521
+ 'retest.repeater.curl.importHint':
522
+ '只解析 URL、请求方法、请求头与请求体;代理、证书、输出文件等参数会被忽略。',
523
+ 'retest.repeater.curl.parse': '解析并应用',
524
+ 'retest.repeater.curl.empty': '请先粘贴 curl 命令',
525
+ 'retest.repeater.curl.noUrl': '未找到 URL:请提供 URL 或使用 --url',
526
+ 'retest.repeater.curl.unterminatedQuote': '命令中的引号未闭合',
527
+ 'retest.repeater.curl.applied': '已应用 curl 请求'
458
528
  },
459
529
  en: {
460
530
  // Left navigation card
@@ -486,6 +556,7 @@ export const retestMessages: MessageBundle = {
486
556
  'retest.repeater.stepN': 'Step {n}',
487
557
  'retest.repeater.followRedirect': 'Follow redirect',
488
558
  'retest.repeater.viewRaw': 'Raw',
559
+ 'retest.repeater.formatJson': 'Format',
489
560
  'retest.repeater.viewHtml': 'Render',
490
561
  'retest.repeater.htmlPreview': 'Rendered HTML preview',
491
562
  'retest.repeater.emptyResponse': 'Send a request to inspect the raw response',
@@ -931,6 +1002,79 @@ export const retestMessages: MessageBundle = {
931
1002
  'retest.config.meta.noActiveProvider': 'No active provider selected',
932
1003
  'retest.config.meta.providerCount': '{count} providers',
933
1004
  'retest.config.noProvidersActiveHint':
934
- 'Configure at least one model provider before generating a PoC.'
1005
+ 'Configure at least one model provider before generating a PoC.',
1006
+
1007
+ // ------------------------------------------------------------------
1008
+ // Single-Repeater additions (history / favorites / curl import+export).
1009
+ // Appended block; existing keys above are untouched.
1010
+ // ------------------------------------------------------------------
1011
+ 'retest.repeater.requestSection': 'Request',
1012
+ 'retest.repeater.formatRequest': 'Format',
1013
+ 'retest.repeater.formatRequestTitle': 'Format the JSON request body',
1014
+ 'retest.repeater.formatRequestFailed': 'The request body is not valid JSON and cannot be formatted',
1015
+
1016
+ // Send history
1017
+ 'retest.repeater.history.open': 'History',
1018
+ 'retest.repeater.history.title': 'Send history',
1019
+ 'retest.repeater.history.description':
1020
+ 'Recent sends; click one to restore both the request and the response.',
1021
+ 'retest.repeater.history.loading': 'Loading send history…',
1022
+ 'retest.repeater.history.error': 'Could not load send history: {error}',
1023
+ 'retest.repeater.history.empty': 'No sends recorded yet',
1024
+ 'retest.repeater.history.emptyHint':
1025
+ 'Every successful send is recorded locally for later replay.',
1026
+ 'retest.repeater.history.itemAria': '{method} {url}, status {status}, {time}',
1027
+ 'retest.repeater.history.noResponse': 'No response',
1028
+ 'retest.repeater.history.restore': 'Click to restore',
1029
+ 'retest.repeater.history.refresh': 'Refresh send history',
1030
+ 'retest.repeater.history.footerHint': 'Stored locally, up to 50 entries',
1031
+ 'retest.repeater.history.clear': 'Clear history',
1032
+ 'retest.repeater.history.cleared': 'Send history cleared',
1033
+ 'retest.repeater.history.clearFailed': 'Could not clear send history: {error}',
1034
+
1035
+ // Favorites
1036
+ 'retest.repeater.favorites.open': 'Favorites',
1037
+ 'retest.repeater.favorites.title': 'Saved requests',
1038
+ 'retest.repeater.favorites.description':
1039
+ 'Save the current request under a name and restore request + response later.',
1040
+ 'retest.repeater.favorites.nameLabel': 'Name',
1041
+ 'retest.repeater.favorites.namePlaceholder': 'e.g. invoice lookup after login',
1042
+ 'retest.repeater.favorites.nameInvalid': 'Name must be 1–80 characters',
1043
+ 'retest.repeater.favorites.save': 'Save current request',
1044
+ 'retest.repeater.favorites.saving': 'Saving…',
1045
+ 'retest.repeater.favorites.saveHint':
1046
+ 'Stores the raw request and the latest response; names are capped at 80 characters.',
1047
+ 'retest.repeater.favorites.invalidRequest':
1048
+ 'The editor content does not parse; fix the request line or headers before saving.',
1049
+ 'retest.repeater.favorites.saved': 'Current request saved',
1050
+ 'retest.repeater.favorites.saveFailed': 'Could not save request: {error}',
1051
+ 'retest.repeater.favorites.loading': 'Loading saved requests…',
1052
+ 'retest.repeater.favorites.error': 'Could not load saved requests: {error}',
1053
+ 'retest.repeater.favorites.empty': 'No saved requests yet',
1054
+ 'retest.repeater.favorites.emptyHint': 'Save a request now to restore it at any time.',
1055
+ 'retest.repeater.favorites.loadAria': 'Load saved request: {name}',
1056
+ 'retest.repeater.favorites.deleteAria': 'Delete saved request: {name}',
1057
+ 'retest.repeater.favorites.deleted': 'Saved request deleted',
1058
+ 'retest.repeater.favorites.deleteFailed': 'Could not delete saved request: {error}',
1059
+ 'retest.repeater.favorites.footerHint': 'Stored locally, up to 50 entries',
1060
+
1061
+ // curl import / export
1062
+ 'retest.repeater.curl.import': 'Import curl',
1063
+ 'retest.repeater.curl.export': 'Export curl',
1064
+ 'retest.repeater.curl.exported': 'curl command copied',
1065
+ 'retest.repeater.curl.parseFailed': 'The current request does not parse; cannot export curl',
1066
+ 'retest.repeater.curl.importTitle': 'Import curl command',
1067
+ 'retest.repeater.curl.importDescription':
1068
+ 'Supports bash/zsh and Windows cmd styles; the parsed request replaces the editor content.',
1069
+ 'retest.repeater.curl.inputLabel': 'curl command',
1070
+ 'retest.repeater.curl.inputPlaceholder':
1071
+ "curl 'https://example.com/api' -H 'Accept: application/json' -d 'a=1'",
1072
+ 'retest.repeater.curl.importHint':
1073
+ 'Only URL, method, headers and body are parsed; proxy, certificate and output options are ignored.',
1074
+ 'retest.repeater.curl.parse': 'Parse & apply',
1075
+ 'retest.repeater.curl.empty': 'Paste a curl command first',
1076
+ 'retest.repeater.curl.noUrl': 'No URL found: include a URL or pass --url',
1077
+ 'retest.repeater.curl.unterminatedQuote': 'The command contains an unclosed quote',
1078
+ 'retest.repeater.curl.applied': 'curl request applied'
935
1079
  }
936
1080
  }
@@ -92,13 +92,23 @@ export const vulnMessages: MessageBundle = {
92
92
  'vuln.toast.exportedMany': '已导出 {count} 份 Markdown 报告',
93
93
  'vuln.toast.exported': 'Markdown 报告已导出',
94
94
  'vuln.toast.exportedPath': '已保存到:{path}',
95
- 'vuln.export.title': '导出 Markdown 报告',
96
- 'vuln.export.description': '共 {count} 份报告。可指定导出目录,留空则使用默认目录。',
95
+ 'vuln.export.title': '导出报告',
97
96
  'vuln.export.dirLabel': '导出目录',
97
+ 'vuln.export.browse': '选择文件夹',
98
98
  'vuln.export.dirPlaceholder': '例如 C:\\Users\\you\\Downloads',
99
- 'vuln.export.dirHint': '留空:~/.cortex/exports/<时间戳>/;支持绝对路径或 ~ 开头路径。',
100
99
  'vuln.export.dirInvalid': '请输入绝对路径(如 C:\\Reports 或 ~/Reports)',
101
100
  'vuln.export.confirm': '导出',
101
+ 'vuln.export.formatLabel': '报告格式',
102
+ 'vuln.export.formatMd': 'Markdown (.md)',
103
+ 'vuln.export.formatDocx': 'Word (.docx)',
104
+ 'vuln.export.formatPdf': 'PDF (.pdf)',
105
+ 'vuln.dirPicker.title': '选择导出文件夹',
106
+ 'vuln.dirPicker.go': '前往',
107
+ 'vuln.dirPicker.up': '上一级',
108
+ 'vuln.dirPicker.loading': '加载中…',
109
+ 'vuln.dirPicker.empty': '该目录下没有子文件夹',
110
+ 'vuln.dirPicker.error': '读取目录失败:{error}',
111
+ 'vuln.dirPicker.select': '使用此文件夹',
102
112
  'vuln.toast.exportFailed': '导出失败:{error}',
103
113
  'vuln.toast.deleted': '已删除 {id}',
104
114
  'vuln.toast.bulkDeleted': '已删除 {count} 条漏洞',
@@ -210,13 +220,23 @@ export const vulnMessages: MessageBundle = {
210
220
  'vuln.toast.exportedMany': 'Exported {count} Markdown reports',
211
221
  'vuln.toast.exported': 'Markdown report exported',
212
222
  'vuln.toast.exportedPath': 'Saved to: {path}',
213
- 'vuln.export.title': 'Export Markdown report',
214
- 'vuln.export.description': '{count} report(s). Choose an output directory, or leave empty to use the default.',
223
+ 'vuln.export.title': 'Export report',
215
224
  'vuln.export.dirLabel': 'Output directory',
225
+ 'vuln.export.browse': 'Choose folder',
216
226
  'vuln.export.dirPlaceholder': 'e.g. C:\\Users\\you\\Downloads',
217
- 'vuln.export.dirHint': 'Empty: ~/.cortex/exports/<timestamp>/; absolute or ~-prefixed paths are accepted.',
218
227
  'vuln.export.dirInvalid': 'Enter an absolute path (e.g. C:\\Reports or ~/Reports)',
219
228
  'vuln.export.confirm': 'Export',
229
+ 'vuln.export.formatLabel': 'Report format',
230
+ 'vuln.export.formatMd': 'Markdown (.md)',
231
+ 'vuln.export.formatDocx': 'Word (.docx)',
232
+ 'vuln.export.formatPdf': 'PDF (.pdf)',
233
+ 'vuln.dirPicker.title': 'Choose export folder',
234
+ 'vuln.dirPicker.go': 'Go',
235
+ 'vuln.dirPicker.up': 'Up',
236
+ 'vuln.dirPicker.loading': 'Loading…',
237
+ 'vuln.dirPicker.empty': 'No subfolders in this folder',
238
+ 'vuln.dirPicker.error': 'Failed to read folder: {error}',
239
+ 'vuln.dirPicker.select': 'Use this folder',
220
240
  'vuln.toast.exportFailed': 'Export failed: {error}',
221
241
  'vuln.toast.deleted': 'Deleted {id}',
222
242
  'vuln.toast.bulkDeleted': 'Deleted {count} vulnerabilities',