@talex-touch/utils 1.0.40 → 1.0.44

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 (235) hide show
  1. package/.eslintcache +1 -0
  2. package/__tests__/cloud-sync-sdk.test.ts +442 -0
  3. package/__tests__/icons/icons.test.ts +84 -0
  4. package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
  5. package/__tests__/power-sdk.test.ts +143 -0
  6. package/__tests__/preset-export-types.test.ts +108 -0
  7. package/__tests__/search/fuzzy-match.test.ts +137 -0
  8. package/__tests__/transport/port-policy.test.ts +44 -0
  9. package/__tests__/transport-domain-sdks.test.ts +152 -0
  10. package/__tests__/types/update.test.ts +67 -0
  11. package/account/account-sdk.ts +915 -0
  12. package/account/index.ts +2 -0
  13. package/account/types.ts +321 -0
  14. package/analytics/client.ts +136 -0
  15. package/analytics/index.ts +2 -0
  16. package/analytics/types.ts +156 -0
  17. package/animation/auto-resize.ts +322 -0
  18. package/animation/window-node.ts +26 -19
  19. package/auth/clerk-types.ts +12 -30
  20. package/auth/index.ts +0 -2
  21. package/auth/useAuthState.ts +6 -14
  22. package/base/index.ts +2 -0
  23. package/base/log-level.ts +105 -0
  24. package/channel/index.ts +170 -69
  25. package/cloud-sync/cloud-sync-sdk.ts +450 -0
  26. package/cloud-sync/index.ts +1 -0
  27. package/common/file-scan-utils.ts +17 -9
  28. package/common/index.ts +4 -0
  29. package/common/logger/index.ts +46 -0
  30. package/common/logger/logger-manager.ts +303 -0
  31. package/common/logger/module-logger.ts +270 -0
  32. package/common/logger/transport-logger.ts +234 -0
  33. package/common/logger/types.ts +93 -0
  34. package/common/search/gather.ts +48 -6
  35. package/common/search/index.ts +8 -0
  36. package/common/storage/constants.ts +13 -0
  37. package/common/storage/entity/app-settings.ts +245 -0
  38. package/common/storage/entity/index.ts +3 -0
  39. package/common/storage/entity/layout-atom-types.ts +147 -0
  40. package/common/storage/entity/openers.ts +1 -0
  41. package/common/storage/entity/preset-cloud-api.ts +132 -0
  42. package/common/storage/entity/preset-export-types.ts +256 -0
  43. package/common/storage/entity/shortcut-settings.ts +1 -0
  44. package/common/storage/shortcut-storage.ts +11 -0
  45. package/common/utils/clone-diagnostics.ts +105 -0
  46. package/common/utils/file.ts +16 -8
  47. package/common/utils/index.ts +6 -2
  48. package/common/utils/payload-preview.ts +173 -0
  49. package/common/utils/polling.ts +167 -13
  50. package/common/utils/safe-path.ts +103 -0
  51. package/common/utils/safe-shell.ts +115 -0
  52. package/common/utils/task-queue.ts +4 -1
  53. package/core-box/builder/tuff-builder.ts +0 -1
  54. package/core-box/index.ts +1 -1
  55. package/core-box/recommendation.ts +38 -1
  56. package/core-box/tuff/tuff-dsl.ts +97 -0
  57. package/electron/download-manager.ts +10 -7
  58. package/electron/env-tool.ts +42 -40
  59. package/electron/index.ts +0 -1
  60. package/env/index.ts +156 -0
  61. package/eslint.config.js +55 -0
  62. package/i18n/index.ts +62 -0
  63. package/i18n/locales/en.json +226 -0
  64. package/i18n/locales/zh.json +226 -0
  65. package/i18n/message-keys.ts +236 -0
  66. package/i18n/resolver.ts +181 -0
  67. package/icons/index.ts +257 -0
  68. package/icons/svg.ts +69 -0
  69. package/index.ts +9 -1
  70. package/intelligence/client.ts +72 -42
  71. package/market/constants.ts +21 -3
  72. package/market/index.ts +1 -1
  73. package/market/types.ts +20 -5
  74. package/package.json +15 -5
  75. package/permission/index.ts +143 -46
  76. package/permission/legacy.ts +26 -0
  77. package/permission/registry.ts +304 -0
  78. package/permission/types.ts +164 -0
  79. package/plugin/channel.ts +68 -39
  80. package/plugin/index.ts +82 -8
  81. package/plugin/install.ts +3 -0
  82. package/plugin/log/types.ts +22 -5
  83. package/plugin/node/logger-manager.ts +11 -3
  84. package/plugin/node/logger.ts +24 -17
  85. package/plugin/preload.ts +25 -2
  86. package/plugin/providers/index.ts +4 -0
  87. package/plugin/providers/market-client.ts +218 -0
  88. package/plugin/providers/npm-provider.ts +228 -0
  89. package/plugin/providers/tpex-provider.ts +297 -0
  90. package/plugin/providers/tpex-types.ts +34 -0
  91. package/plugin/sdk/box-items.ts +14 -0
  92. package/plugin/sdk/box-sdk.ts +64 -0
  93. package/plugin/sdk/channel.ts +119 -4
  94. package/plugin/sdk/clipboard.ts +26 -12
  95. package/plugin/sdk/cloud-sync.ts +113 -0
  96. package/plugin/sdk/common.ts +19 -11
  97. package/plugin/sdk/core-box.ts +6 -15
  98. package/plugin/sdk/division-box.ts +160 -65
  99. package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
  100. package/plugin/sdk/feature-sdk.ts +111 -76
  101. package/plugin/sdk/flow.ts +146 -45
  102. package/plugin/sdk/hooks/bridge.ts +113 -49
  103. package/plugin/sdk/hooks/life-cycle.ts +35 -16
  104. package/plugin/sdk/index.ts +14 -3
  105. package/plugin/sdk/intelligence.ts +87 -0
  106. package/plugin/sdk/meta/README.md +179 -0
  107. package/plugin/sdk/meta-sdk.ts +244 -0
  108. package/plugin/sdk/notification.ts +9 -0
  109. package/plugin/sdk/performance.ts +1 -16
  110. package/plugin/sdk/plugin-info.ts +64 -0
  111. package/plugin/sdk/power.ts +155 -0
  112. package/plugin/sdk/recommend.ts +21 -0
  113. package/plugin/sdk/service/index.ts +12 -8
  114. package/plugin/sdk/sqlite.ts +141 -0
  115. package/plugin/sdk/storage.ts +2 -6
  116. package/plugin/sdk/system.ts +2 -9
  117. package/plugin/sdk/temp-files.ts +41 -0
  118. package/plugin/sdk/touch-sdk.ts +18 -0
  119. package/plugin/sdk/types.ts +44 -4
  120. package/plugin/sdk/window/index.ts +12 -9
  121. package/plugin/sdk-version.ts +231 -0
  122. package/preload/renderer.ts +3 -2
  123. package/renderer/hooks/arg-mapper.ts +34 -6
  124. package/renderer/hooks/index.ts +13 -0
  125. package/renderer/hooks/initialize.ts +2 -1
  126. package/renderer/hooks/use-agent-market-sdk.ts +7 -0
  127. package/renderer/hooks/use-agent-market.ts +106 -0
  128. package/renderer/hooks/use-agents-sdk.ts +7 -0
  129. package/renderer/hooks/use-app-sdk.ts +7 -0
  130. package/renderer/hooks/use-channel.ts +33 -4
  131. package/renderer/hooks/use-download-sdk.ts +21 -0
  132. package/renderer/hooks/use-intelligence-sdk.ts +7 -0
  133. package/renderer/hooks/use-intelligence-stats.ts +290 -0
  134. package/renderer/hooks/use-intelligence.ts +202 -104
  135. package/renderer/hooks/use-market-sdk.ts +16 -0
  136. package/renderer/hooks/use-notification-sdk.ts +7 -0
  137. package/renderer/hooks/use-permission-sdk.ts +7 -0
  138. package/renderer/hooks/use-permission.ts +325 -0
  139. package/renderer/hooks/use-platform-sdk.ts +7 -0
  140. package/renderer/hooks/use-plugin-sdk.ts +16 -0
  141. package/renderer/hooks/use-settings-sdk.ts +7 -0
  142. package/renderer/hooks/use-update-sdk.ts +21 -0
  143. package/renderer/index.ts +1 -0
  144. package/renderer/ref.ts +19 -10
  145. package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
  146. package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
  147. package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
  148. package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
  149. package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
  150. package/renderer/shared/components/index.ts +5 -0
  151. package/renderer/shared/components/shims-vue.d.ts +5 -0
  152. package/renderer/shared/index.ts +2 -0
  153. package/renderer/shared/plugin-detail.ts +62 -0
  154. package/renderer/storage/app-settings.ts +3 -1
  155. package/renderer/storage/base-storage.ts +508 -82
  156. package/renderer/storage/intelligence-storage.ts +37 -46
  157. package/renderer/storage/openers.ts +3 -1
  158. package/renderer/storage/storage-subscription.ts +126 -42
  159. package/renderer/touch-sdk/env.ts +10 -10
  160. package/renderer/touch-sdk/index.ts +114 -18
  161. package/renderer/touch-sdk/terminal.ts +24 -13
  162. package/search/feature-matcher.ts +279 -0
  163. package/search/fuzzy-match.ts +64 -34
  164. package/search/index.ts +10 -0
  165. package/search/levenshtein-utils.ts +17 -11
  166. package/transport/errors.ts +310 -0
  167. package/transport/event/builder.ts +378 -0
  168. package/transport/event/index.ts +7 -0
  169. package/transport/event/types.ts +292 -0
  170. package/transport/events/index.ts +2670 -0
  171. package/transport/events/meta-overlay.ts +79 -0
  172. package/transport/events/types/agents.ts +177 -0
  173. package/transport/events/types/app-index.ts +9 -0
  174. package/transport/events/types/app.ts +475 -0
  175. package/transport/events/types/box-item.ts +222 -0
  176. package/transport/events/types/clipboard.ts +80 -0
  177. package/transport/events/types/core-box.ts +534 -0
  178. package/transport/events/types/device-idle.ts +7 -0
  179. package/transport/events/types/division-box.ts +99 -0
  180. package/transport/events/types/download.ts +115 -0
  181. package/transport/events/types/file-index.ts +73 -0
  182. package/transport/events/types/flow.ts +149 -0
  183. package/transport/events/types/index.ts +70 -0
  184. package/transport/events/types/market.ts +39 -0
  185. package/transport/events/types/meta-overlay.ts +184 -0
  186. package/transport/events/types/notification.ts +140 -0
  187. package/transport/events/types/permission.ts +90 -0
  188. package/transport/events/types/platform.ts +8 -0
  189. package/transport/events/types/plugin.ts +620 -0
  190. package/transport/events/types/sentry.ts +20 -0
  191. package/transport/events/types/storage.ts +208 -0
  192. package/transport/events/types/transport.ts +60 -0
  193. package/transport/events/types/tray.ts +16 -0
  194. package/transport/events/types/update.ts +78 -0
  195. package/transport/index.ts +139 -0
  196. package/transport/main.ts +2 -0
  197. package/transport/sdk/constants.ts +29 -0
  198. package/transport/sdk/domains/agents-market.ts +47 -0
  199. package/transport/sdk/domains/agents.ts +62 -0
  200. package/transport/sdk/domains/app.ts +48 -0
  201. package/transport/sdk/domains/disposable.ts +35 -0
  202. package/transport/sdk/domains/download.ts +139 -0
  203. package/transport/sdk/domains/index.ts +13 -0
  204. package/transport/sdk/domains/intelligence.ts +616 -0
  205. package/transport/sdk/domains/market.ts +35 -0
  206. package/transport/sdk/domains/notification.ts +62 -0
  207. package/transport/sdk/domains/permission.ts +85 -0
  208. package/transport/sdk/domains/platform.ts +19 -0
  209. package/transport/sdk/domains/plugin.ts +144 -0
  210. package/transport/sdk/domains/settings.ts +92 -0
  211. package/transport/sdk/domains/update.ts +64 -0
  212. package/transport/sdk/index.ts +60 -0
  213. package/transport/sdk/main-transport.ts +710 -0
  214. package/transport/sdk/main.ts +9 -0
  215. package/transport/sdk/plugin-transport.ts +654 -0
  216. package/transport/sdk/port-policy.ts +38 -0
  217. package/transport/sdk/renderer-transport.ts +1165 -0
  218. package/transport/types.ts +605 -0
  219. package/types/agent.ts +399 -0
  220. package/types/cloud-sync.ts +157 -0
  221. package/types/division-box.ts +47 -27
  222. package/types/download.ts +1 -0
  223. package/types/flow.ts +63 -12
  224. package/types/icon.ts +2 -1
  225. package/types/index.ts +5 -0
  226. package/types/intelligence.ts +1492 -81
  227. package/types/modules/base.ts +2 -0
  228. package/types/path-browserify.d.ts +5 -0
  229. package/types/platform.ts +12 -0
  230. package/types/startup-info.ts +32 -0
  231. package/types/touch-app-core.ts +8 -8
  232. package/types/update.ts +94 -1
  233. package/vitest.config.ts +25 -0
  234. package/auth/useClerkConfig.ts +0 -40
  235. package/auth/useClerkProvider.ts +0 -52
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Permission Registry
3
+ *
4
+ * Defines all available permissions in the system.
5
+ */
6
+
7
+ import type { PermissionDefinition } from './types'
8
+ import { PermissionCategory, PermissionRiskLevel } from './types'
9
+
10
+ /**
11
+ * All permission definitions
12
+ */
13
+ export const PERMISSIONS: PermissionDefinition[] = [
14
+ // Filesystem permissions
15
+ {
16
+ id: 'fs.read',
17
+ category: PermissionCategory.FILESYSTEM,
18
+ risk: PermissionRiskLevel.MEDIUM,
19
+ nameKey: 'permission.fs.read.name',
20
+ descKey: 'permission.fs.read.desc',
21
+ icon: 'FileText',
22
+ },
23
+ {
24
+ id: 'fs.write',
25
+ category: PermissionCategory.FILESYSTEM,
26
+ risk: PermissionRiskLevel.HIGH,
27
+ nameKey: 'permission.fs.write.name',
28
+ descKey: 'permission.fs.write.desc',
29
+ icon: 'FilePen',
30
+ },
31
+ {
32
+ id: 'fs.execute',
33
+ category: PermissionCategory.FILESYSTEM,
34
+ risk: PermissionRiskLevel.HIGH,
35
+ nameKey: 'permission.fs.execute.name',
36
+ descKey: 'permission.fs.execute.desc',
37
+ icon: 'Terminal',
38
+ },
39
+ {
40
+ id: 'fs.tfile',
41
+ category: PermissionCategory.FILESYSTEM,
42
+ risk: PermissionRiskLevel.MEDIUM,
43
+ nameKey: 'permission.fs.tfile.name',
44
+ descKey: 'permission.fs.tfile.desc',
45
+ icon: 'FileText',
46
+ },
47
+
48
+ // Clipboard permissions
49
+ {
50
+ id: 'clipboard.read',
51
+ category: PermissionCategory.CLIPBOARD,
52
+ risk: PermissionRiskLevel.MEDIUM,
53
+ nameKey: 'permission.clipboard.read.name',
54
+ descKey: 'permission.clipboard.read.desc',
55
+ icon: 'ClipboardCopy',
56
+ },
57
+ {
58
+ id: 'clipboard.write',
59
+ category: PermissionCategory.CLIPBOARD,
60
+ risk: PermissionRiskLevel.LOW,
61
+ nameKey: 'permission.clipboard.write.name',
62
+ descKey: 'permission.clipboard.write.desc',
63
+ icon: 'ClipboardPaste',
64
+ },
65
+
66
+ // Network permissions
67
+ {
68
+ id: 'network.local',
69
+ category: PermissionCategory.NETWORK,
70
+ risk: PermissionRiskLevel.LOW,
71
+ nameKey: 'permission.network.local.name',
72
+ descKey: 'permission.network.local.desc',
73
+ icon: 'Wifi',
74
+ },
75
+ {
76
+ id: 'network.internet',
77
+ category: PermissionCategory.NETWORK,
78
+ risk: PermissionRiskLevel.MEDIUM,
79
+ nameKey: 'permission.network.internet.name',
80
+ descKey: 'permission.network.internet.desc',
81
+ icon: 'Globe',
82
+ },
83
+ {
84
+ id: 'network.download',
85
+ category: PermissionCategory.NETWORK,
86
+ risk: PermissionRiskLevel.MEDIUM,
87
+ nameKey: 'permission.network.download.name',
88
+ descKey: 'permission.network.download.desc',
89
+ icon: 'Download',
90
+ },
91
+
92
+ // System permissions
93
+ {
94
+ id: 'system.shell',
95
+ category: PermissionCategory.SYSTEM,
96
+ risk: PermissionRiskLevel.HIGH,
97
+ nameKey: 'permission.system.shell.name',
98
+ descKey: 'permission.system.shell.desc',
99
+ icon: 'Terminal',
100
+ },
101
+ {
102
+ id: 'system.notification',
103
+ category: PermissionCategory.SYSTEM,
104
+ risk: PermissionRiskLevel.LOW,
105
+ nameKey: 'permission.system.notification.name',
106
+ descKey: 'permission.system.notification.desc',
107
+ icon: 'Bell',
108
+ },
109
+ {
110
+ id: 'system.tray',
111
+ category: PermissionCategory.SYSTEM,
112
+ risk: PermissionRiskLevel.MEDIUM,
113
+ nameKey: 'permission.system.tray.name',
114
+ descKey: 'permission.system.tray.desc',
115
+ icon: 'PanelTop',
116
+ },
117
+
118
+ // Intelligence permissions
119
+ {
120
+ id: 'intelligence.basic',
121
+ category: PermissionCategory.INTELLIGENCE,
122
+ risk: PermissionRiskLevel.LOW,
123
+ nameKey: 'permission.intelligence.basic.name',
124
+ descKey: 'permission.intelligence.basic.desc',
125
+ icon: 'Bot',
126
+ },
127
+ {
128
+ id: 'intelligence.admin',
129
+ category: PermissionCategory.INTELLIGENCE,
130
+ risk: PermissionRiskLevel.HIGH,
131
+ nameKey: 'permission.intelligence.admin.name',
132
+ descKey: 'permission.intelligence.admin.desc',
133
+ icon: 'Shield',
134
+ },
135
+ {
136
+ id: 'intelligence.agents',
137
+ category: PermissionCategory.INTELLIGENCE,
138
+ risk: PermissionRiskLevel.HIGH,
139
+ nameKey: 'permission.intelligence.agents.name',
140
+ descKey: 'permission.intelligence.agents.desc',
141
+ icon: 'Users',
142
+ },
143
+
144
+ // Storage permissions
145
+ {
146
+ id: 'storage.plugin',
147
+ category: PermissionCategory.STORAGE,
148
+ risk: PermissionRiskLevel.LOW,
149
+ nameKey: 'permission.storage.plugin.name',
150
+ descKey: 'permission.storage.plugin.desc',
151
+ icon: 'Database',
152
+ },
153
+ {
154
+ id: 'storage.shared',
155
+ category: PermissionCategory.STORAGE,
156
+ risk: PermissionRiskLevel.MEDIUM,
157
+ nameKey: 'permission.storage.shared.name',
158
+ descKey: 'permission.storage.shared.desc',
159
+ icon: 'Share2',
160
+ },
161
+ {
162
+ id: 'storage.sqlite',
163
+ category: PermissionCategory.STORAGE,
164
+ risk: PermissionRiskLevel.MEDIUM,
165
+ nameKey: 'permission.storage.sqlite.name',
166
+ descKey: 'permission.storage.sqlite.desc',
167
+ icon: 'Database',
168
+ },
169
+
170
+ // Window permissions
171
+ {
172
+ id: 'window.create',
173
+ category: PermissionCategory.WINDOW,
174
+ risk: PermissionRiskLevel.LOW,
175
+ nameKey: 'permission.window.create.name',
176
+ descKey: 'permission.window.create.desc',
177
+ icon: 'AppWindow',
178
+ },
179
+ {
180
+ id: 'window.capture',
181
+ category: PermissionCategory.WINDOW,
182
+ risk: PermissionRiskLevel.HIGH,
183
+ nameKey: 'permission.window.capture.name',
184
+ descKey: 'permission.window.capture.desc',
185
+ icon: 'Camera',
186
+ },
187
+ ]
188
+
189
+ export function normalizePermissionId(id: string): string {
190
+ return id
191
+ }
192
+
193
+ export function getPermissionIdCandidates(id: string): string[] {
194
+ return [normalizePermissionId(id)]
195
+ }
196
+
197
+ /**
198
+ * Permission registry class
199
+ */
200
+ export class PermissionRegistry {
201
+ private permissions: Map<string, PermissionDefinition> = new Map()
202
+
203
+ constructor() {
204
+ // Register all built-in permissions
205
+ PERMISSIONS.forEach((p) => this.permissions.set(normalizePermissionId(p.id), p))
206
+ }
207
+
208
+ /**
209
+ * Get permission definition by ID
210
+ */
211
+ get(id: string): PermissionDefinition | undefined {
212
+ return this.permissions.get(normalizePermissionId(id))
213
+ }
214
+
215
+ /**
216
+ * Get all permissions
217
+ */
218
+ all(): PermissionDefinition[] {
219
+ return Array.from(this.permissions.values())
220
+ }
221
+
222
+ /**
223
+ * Get permissions by category
224
+ */
225
+ byCategory(category: PermissionCategory): PermissionDefinition[] {
226
+ return this.all().filter(p => p.category === category)
227
+ }
228
+
229
+ /**
230
+ * Get permissions by risk level
231
+ */
232
+ byRisk(risk: PermissionRiskLevel): PermissionDefinition[] {
233
+ return this.all().filter(p => p.risk === risk)
234
+ }
235
+
236
+ /**
237
+ * Check if permission exists
238
+ */
239
+ has(id: string): boolean {
240
+ return this.permissions.has(normalizePermissionId(id))
241
+ }
242
+
243
+ /**
244
+ * Register custom permission
245
+ */
246
+ register(permission: PermissionDefinition): void {
247
+ this.permissions.set(normalizePermissionId(permission.id), permission)
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Singleton permission registry
253
+ */
254
+ export const permissionRegistry = new PermissionRegistry()
255
+
256
+ /**
257
+ * Permission ID constants for type safety
258
+ */
259
+ export const PermissionIds = {
260
+ // Filesystem
261
+ FS_READ: 'fs.read',
262
+ FS_WRITE: 'fs.write',
263
+ FS_EXECUTE: 'fs.execute',
264
+ FS_TFILE: 'fs.tfile',
265
+
266
+ // Clipboard
267
+ CLIPBOARD_READ: 'clipboard.read',
268
+ CLIPBOARD_WRITE: 'clipboard.write',
269
+
270
+ // Network
271
+ NETWORK_LOCAL: 'network.local',
272
+ NETWORK_INTERNET: 'network.internet',
273
+ NETWORK_DOWNLOAD: 'network.download',
274
+
275
+ // System
276
+ SYSTEM_SHELL: 'system.shell',
277
+ SYSTEM_NOTIFICATION: 'system.notification',
278
+ SYSTEM_TRAY: 'system.tray',
279
+
280
+ // Intelligence
281
+ INTELLIGENCE_BASIC: 'intelligence.basic',
282
+ INTELLIGENCE_ADMIN: 'intelligence.admin',
283
+ INTELLIGENCE_AGENTS: 'intelligence.agents',
284
+
285
+ // Storage
286
+ STORAGE_PLUGIN: 'storage.plugin',
287
+ STORAGE_SHARED: 'storage.shared',
288
+ STORAGE_SQLITE: 'storage.sqlite',
289
+
290
+ // Window
291
+ WINDOW_CREATE: 'window.create',
292
+ WINDOW_CAPTURE: 'window.capture',
293
+ } as const
294
+
295
+ export type PermissionId = (typeof PermissionIds)[keyof typeof PermissionIds]
296
+
297
+ /**
298
+ * Default permissions that are auto-granted
299
+ */
300
+ export const DEFAULT_PERMISSIONS: string[] = [
301
+ PermissionIds.STORAGE_PLUGIN,
302
+ PermissionIds.CLIPBOARD_WRITE,
303
+ PermissionIds.WINDOW_CREATE,
304
+ ]
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Permission System Types
3
+ *
4
+ * Defines the permission model for plugin security.
5
+ */
6
+
7
+ /**
8
+ * Permission category
9
+ */
10
+ export enum PermissionCategory {
11
+ FILESYSTEM = 'fs',
12
+ CLIPBOARD = 'clipboard',
13
+ NETWORK = 'network',
14
+ SYSTEM = 'system',
15
+ INTELLIGENCE = 'intelligence',
16
+ STORAGE = 'storage',
17
+ WINDOW = 'window',
18
+ }
19
+
20
+ /**
21
+ * Risk level for permissions
22
+ */
23
+ export enum PermissionRiskLevel {
24
+ LOW = 'low',
25
+ MEDIUM = 'medium',
26
+ HIGH = 'high',
27
+ }
28
+
29
+ /**
30
+ * Permission definition
31
+ */
32
+ export interface PermissionDefinition {
33
+ /** Permission ID (e.g., 'fs.read') */
34
+ id: string
35
+ /** Category */
36
+ category: PermissionCategory
37
+ /** Risk level */
38
+ risk: PermissionRiskLevel
39
+ /** i18n key for display name */
40
+ nameKey: string
41
+ /** i18n key for description */
42
+ descKey: string
43
+ /** Icon name (lucide icon) */
44
+ icon?: string
45
+ }
46
+
47
+ /**
48
+ * Permission grant record
49
+ */
50
+ export interface PermissionGrant {
51
+ /** Plugin ID */
52
+ pluginId: string
53
+ /** Permission ID */
54
+ permissionId: string
55
+ /** Grant timestamp */
56
+ grantedAt: number
57
+ /** How it was granted */
58
+ grantedBy: 'user' | 'auto' | 'trust'
59
+ /** Expiration timestamp (optional) */
60
+ expiresAt?: number
61
+ }
62
+
63
+ /**
64
+ * Permission denial record
65
+ */
66
+ export interface PermissionDenial {
67
+ /** Plugin ID */
68
+ pluginId: string
69
+ /** Permission ID */
70
+ permissionId: string
71
+ /** Denial timestamp */
72
+ deniedAt: number
73
+ /** Reason for denial */
74
+ reason?: string
75
+ }
76
+
77
+ /**
78
+ * Permission check result
79
+ */
80
+ export interface PermissionCheckResult {
81
+ /** Permission ID */
82
+ permissionId: string
83
+ /** Whether permission is granted */
84
+ granted: boolean
85
+ /** Grant details if granted */
86
+ grant?: PermissionGrant
87
+ /** Whether enforcement is active (sdkapi check) */
88
+ enforced: boolean
89
+ /** Warning message if any */
90
+ warning?: string
91
+ }
92
+
93
+ /**
94
+ * Plugin permission status
95
+ */
96
+ export interface PluginPermissionStatus {
97
+ /** Plugin ID */
98
+ pluginId: string
99
+ /** SDK API version */
100
+ sdkapi?: number
101
+ /** Whether permission enforcement is active */
102
+ enforcePermissions: boolean
103
+ /** Required permissions from manifest */
104
+ required: string[]
105
+ /** Optional permissions from manifest */
106
+ optional: string[]
107
+ /** Granted permissions */
108
+ granted: string[]
109
+ /** Denied permissions */
110
+ denied: string[]
111
+ /** Missing required permissions */
112
+ missingRequired: string[]
113
+ /** Compatibility warning */
114
+ warning?: string
115
+ }
116
+
117
+ /**
118
+ * Permission request for UI prompt
119
+ */
120
+ export interface PermissionRequest {
121
+ /** Plugin ID */
122
+ pluginId: string
123
+ /** Plugin display name */
124
+ pluginName: string
125
+ /** Permission ID */
126
+ permissionId: string
127
+ /** Reason from manifest */
128
+ reason?: string
129
+ /** Context of the request */
130
+ context?: Record<string, unknown>
131
+ }
132
+
133
+ /**
134
+ * Audit log entry
135
+ */
136
+ export interface PermissionAuditLog {
137
+ /** Log ID */
138
+ id: string
139
+ /** Timestamp */
140
+ timestamp: number
141
+ /** Plugin ID */
142
+ pluginId: string
143
+ /** Permission ID */
144
+ permissionId: string
145
+ /** Action type */
146
+ action: 'granted' | 'denied' | 'revoked' | 'used' | 'blocked'
147
+ /** Additional context */
148
+ context?: Record<string, unknown>
149
+ }
150
+
151
+ /**
152
+ * Manifest permission declaration
153
+ */
154
+ export interface ManifestPermissions {
155
+ /** Required permissions - plugin won't work without these */
156
+ required?: string[]
157
+ /** Optional permissions - can be granted later */
158
+ optional?: string[]
159
+ }
160
+
161
+ /**
162
+ * Permission reasons in manifest
163
+ */
164
+ export type ManifestPermissionReasons = Record<string, string>
package/plugin/channel.ts CHANGED
@@ -9,25 +9,45 @@ import {
9
9
  ChannelType,
10
10
  DataCode,
11
11
  } from '../channel'
12
+ import { getLogger } from '../common/logger'
13
+ import { findCloneIssue, isCloneError, summarizeClonePayload } from '../common/utils/clone-diagnostics'
14
+ import { formatPayloadPreview } from '../common/utils/payload-preview'
15
+ import { hasWindow } from '../env'
12
16
 
13
- const CHANNEL_DEFAULT_TIMEOUT = 10_000
17
+ const CHANNEL_DEFAULT_TIMEOUT = 60_000
14
18
 
15
19
  let cachedIpcRenderer: IpcRenderer | null = null
20
+ const channelLog = getLogger('plugin-channel')
21
+
22
+ type PluginWindow = Window & {
23
+ $plugin?: { name?: string }
24
+ $channel?: ITouchClientChannel
25
+ electron?: { ipcRenderer?: IpcRenderer }
26
+ }
27
+
28
+ function getPluginWindow(): PluginWindow | undefined {
29
+ return hasWindow() ? (window as unknown as PluginWindow) : undefined
30
+ }
16
31
 
17
32
  // 使用惰性解析避免在打包阶段静态引入 electron
18
33
  function resolveIpcRenderer(): IpcRenderer | null {
19
- if (typeof window !== 'undefined') {
20
- const bridge = (window as any)?.electron
21
- if (bridge?.ipcRenderer)
22
- return bridge.ipcRenderer as IpcRenderer
23
- }
34
+ const globalWindow = getPluginWindow()
35
+ if (globalWindow?.electron?.ipcRenderer)
36
+ return globalWindow.electron.ipcRenderer as IpcRenderer
24
37
 
25
38
  try {
26
- const electron = (globalThis as any)?.electron ?? (eval('require') as any)?.('electron')
27
- if (electron?.ipcRenderer)
28
- return electron.ipcRenderer as IpcRenderer
39
+ const electronFromGlobal = (globalThis as any)?.electron
40
+ if (electronFromGlobal?.ipcRenderer)
41
+ return electronFromGlobal.ipcRenderer as IpcRenderer
42
+
43
+ const requireFromGlobal = (globalThis as any)?.require
44
+ if (typeof requireFromGlobal === 'function') {
45
+ const electron = requireFromGlobal('electron')
46
+ if (electron?.ipcRenderer)
47
+ return electron.ipcRenderer as IpcRenderer
48
+ }
29
49
  }
30
- catch (error) {
50
+ catch {
31
51
  // ignore – will throw below if no ipcRenderer is resolved
32
52
  }
33
53
 
@@ -46,14 +66,17 @@ function ensureIpcRenderer(): IpcRenderer {
46
66
  return cachedIpcRenderer
47
67
  }
48
68
 
69
+ type ChannelListener = (data: StandardChannelData) => unknown
70
+ type PendingCallback = (data: RawStandardChannelData) => void
71
+
49
72
  /**
50
73
  * @deprecated This class is deprecated and will be removed in the future.
51
74
  * Due to the new secret system, ipc message transmission should unique Key, and will inject when ui view attached.
52
75
  */
53
76
  class TouchChannel implements ITouchClientChannel {
54
- channelMap: Map<string, Function[]> = new Map()
77
+ channelMap: Map<string, ChannelListener[]> = new Map()
55
78
 
56
- pendingMap: Map<string, Function> = new Map()
79
+ pendingMap: Map<string, PendingCallback> = new Map()
57
80
 
58
81
  plugin: string
59
82
 
@@ -66,7 +89,7 @@ class TouchChannel implements ITouchClientChannel {
66
89
  }
67
90
 
68
91
  __parse_raw_data(e: IpcRendererEvent | undefined, arg: any): RawStandardChannelData | null {
69
- console.debug('Raw data: ', arg, e)
92
+ channelLog.debug('Raw data', { meta: { payload: formatPayloadPreview(arg) } })
70
93
  if (arg) {
71
94
  const { name, header, code, data, sync } = arg
72
95
 
@@ -86,7 +109,7 @@ class TouchChannel implements ITouchClientChannel {
86
109
  }
87
110
  }
88
111
 
89
- console.error(e, arg)
112
+ channelLog.error('Invalid message payload', { error: { event: e, payload: arg } })
90
113
  return null
91
114
  // throw new Error("Invalid message!");
92
115
  }
@@ -154,7 +177,7 @@ class TouchChannel implements ITouchClientChannel {
154
177
 
155
178
  regChannel(
156
179
  eventName: string,
157
- callback: Function,
180
+ callback: ChannelListener,
158
181
  ): () => void {
159
182
  const listeners = this.channelMap.get(eventName) || []
160
183
 
@@ -176,7 +199,7 @@ class TouchChannel implements ITouchClientChannel {
176
199
  }
177
200
  }
178
201
 
179
- unRegChannel(eventName: string, callback: Function): boolean {
202
+ unRegChannel(eventName: string, callback: ChannelListener): boolean {
180
203
  const listeners = this.channelMap.get(eventName)
181
204
 
182
205
  if (!listeners) {
@@ -200,16 +223,7 @@ class TouchChannel implements ITouchClientChannel {
200
223
  }
201
224
 
202
225
  private formatPayloadPreview(payload: unknown): string {
203
- if (payload === null || payload === undefined)
204
- return String(payload)
205
- if (typeof payload === 'string')
206
- return payload.length > 200 ? `${payload.slice(0, 200)}…` : payload
207
- try {
208
- return JSON.stringify(payload)
209
- }
210
- catch {
211
- return '[unserializable]'
212
- }
226
+ return formatPayloadPreview(payload)
213
227
  }
214
228
 
215
229
  send(eventName: string, arg: any): Promise<any> {
@@ -239,13 +253,20 @@ class TouchChannel implements ITouchClientChannel {
239
253
  }
240
254
  catch (error) {
241
255
  const errorMessage = error instanceof Error ? error.message : String(error)
242
- console.error(
243
- `[PluginChannel] Failed to send "${eventName}": ${errorMessage}`,
244
- { payloadPreview: this.formatPayloadPreview(arg) },
245
- )
256
+ const meta: Record<string, unknown> = {
257
+ payloadPreview: this.formatPayloadPreview(arg)
258
+ }
259
+ if (isCloneError(error)) {
260
+ meta.cloneIssue = findCloneIssue(arg)
261
+ meta.payloadSummary = summarizeClonePayload(arg)
262
+ }
263
+ channelLog.error(`Failed to send \"${eventName}\": ${errorMessage}`, {
264
+ meta,
265
+ error,
266
+ })
246
267
  reject(
247
268
  Object.assign(
248
- new Error(`Failed to send plugin channel message "${eventName}": ${errorMessage}`),
269
+ new Error(`Failed to send plugin channel message \"${eventName}\": ${errorMessage}`),
249
270
  { code: 'plugin_channel_send_failed' },
250
271
  ),
251
272
  )
@@ -258,10 +279,10 @@ class TouchChannel implements ITouchClientChannel {
258
279
  return
259
280
  this.pendingMap.delete(uniqueId)
260
281
  const timeoutError = Object.assign(
261
- new Error(`Plugin channel request "${eventName}" timed out after ${timeoutMs}ms`),
282
+ new Error(`Plugin channel request \"${eventName}\" timed out after ${timeoutMs}ms`),
262
283
  { code: 'plugin_channel_timeout' },
263
284
  )
264
- console.warn(timeoutError.message)
285
+ channelLog.warn(timeoutError.message)
265
286
  reject(timeoutError)
266
287
  }, timeoutMs)
267
288
 
@@ -299,12 +320,19 @@ class TouchChannel implements ITouchClientChannel {
299
320
  }
300
321
  catch (error) {
301
322
  const errorMessage = error instanceof Error ? error.message : String(error)
302
- console.error('[PluginChannel] Failed to sendSync message', {
323
+ const meta: Record<string, unknown> = {
303
324
  eventName,
304
- error: errorMessage,
305
325
  payloadPreview: this.formatPayloadPreview(arg),
326
+ }
327
+ if (isCloneError(error)) {
328
+ meta.cloneIssue = findCloneIssue(arg)
329
+ meta.payloadSummary = summarizeClonePayload(arg)
330
+ }
331
+ channelLog.error('Failed to sendSync message', {
332
+ meta,
333
+ error,
306
334
  })
307
- throw new Error(`Failed to sendSync plugin channel message "${eventName}": ${errorMessage}`)
335
+ throw new Error(`Failed to sendSync plugin channel message \"${eventName}\": ${errorMessage}`)
308
336
  }
309
337
  }
310
338
  }
@@ -313,13 +341,14 @@ let touchChannel: ITouchClientChannel | null = null
313
341
 
314
342
  export function genChannel(): ITouchClientChannel {
315
343
  if (!touchChannel) {
316
- if (typeof window === 'undefined' || !(window as any)?.$plugin?.name) {
344
+ const globalWindow = getPluginWindow()
345
+ const pluginName = globalWindow?.$plugin?.name
346
+ if (!globalWindow || !pluginName) {
317
347
  throw new Error('TouchChannel cannot be initialized outside plugin renderer context')
318
348
  }
319
349
 
320
- const pluginName = (window as any).$plugin.name as string
321
350
  touchChannel = new TouchChannel(pluginName)
322
- ;(window as any).$channel = touchChannel
351
+ globalWindow.$channel = touchChannel
323
352
  }
324
353
 
325
354
  return touchChannel