@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
package/icons/svg.ts ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Built-in SVG icons for offline usage and documentation preview
3
+ * These are inline SVG strings that can be used without UnoCSS CDN
4
+ */
5
+
6
+ export const TuffSvgIcons = {
7
+ // Navigation
8
+ Home: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8z"/></svg>',
9
+ Back: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M20 11H7.83l5.59-5.59L12 4l-8 8l8 8l1.41-1.41L7.83 13H20z"/></svg>',
10
+ Forward: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M4 11h12.17l-5.59-5.59L12 4l8 8l-8 8l-1.41-1.41L16.17 13H4z"/></svg>',
11
+ Menu: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z"/></svg>',
12
+
13
+ // Actions
14
+ Search: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19zm-6 0A4.5 4.5 0 1 1 149.5A4.5 4.5 0 0 1 9.5 14"/></svg>',
15
+ Add: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"/></svg>',
16
+ Delete: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zM19 4h-3.5l-1-1h-5l-1 1H5v2h14z"/></svg>',
17
+ Edit: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75zM20.71 7.04a1 1 0 0 0 0-1.41l-2.34-2.34a1 1 0 0 0-1.41 0l-1.83 1.83l3.75 3.75z"/></svg>',
18
+ Copy: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z"/></svg>',
19
+ Save: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M17 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V7zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3s3 1.34 3 3s-1.34 3-3 3m3-10H5V5h10z"/></svg>',
20
+ Download: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M5 20h14v-2H5zm7-2l5-5h-4V4h-2v9H7z"/></svg>',
21
+ Upload: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M5 20h14v-2H5zm7-18L7 7h4v9h2V7h4z"/></svg>',
22
+ Refresh: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M17.65 6.35A7.96 7.96 0 0 0 12 4a8 8 0 0 0-8 8a88 0 0 0 8 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18a66 0 0 1-6-6a6 6 0 0 1 6-6c1.66 0 3.14.69 4.22 1.78L1311h7V4z"/></svg>',
23
+
24
+ // Status
25
+ Check: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L4.83 12l-1.421.41L9 19L21 7l-1.41-1.41z"/></svg>',
26
+ Close: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>',
27
+ Info: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m1 15h-2v-6h2zm0-8h-2V7h2z"/></svg>',
28
+ Warning: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M1 21h22L12 2zm12-3h-2v-2h2zm0-4h-2v-4h2z"/></svg>',
29
+ Error: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m1 15h-2v-2h2zm0-4h-2V7h2z"/></svg>',
30
+ Success: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m-2 15l-5-5l1.41-1.41L10 14.17l7.59-7.59L19 8z"/></svg>',
31
+ Question: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m1 17h-2v-2h2zm2.07-7.75l-.9.92c-.5.51-.86.97-1.04 1.69c-.08.32-.13.68-.13 1.14h-2v-.5a4.35 4.35 0 0 1 1.17-2.83l1.24-1.26c.46-.44.68-1.1.55-1.8a22 0 0 0-1.39-1.53A2 2 0 0 0 10 9H9.99A2 2 0 0 0 8 11H6c0-2.211.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25"/></svg>',
32
+ Loading: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 4V2A1010 0 0 02 12h2a8 8 0 0 1 8-8"/></svg>',
33
+
34
+ // Files
35
+ File: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M6 2c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm7 7V3.5L18.5 9z"/></svg>',
36
+ Folder: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8z"/></svg>',
37
+ FolderOpen: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2m0 12H4V8h16z"/></svg>',
38
+ Image: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2M8.5 13.5l2.5 3.01L14.5 12l4.5 6H5z"/></svg>',
39
+ Video: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l44v-11z"/></svg>',
40
+ Music: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 3v10.55c-.59-.34-1.27-.55-2-.55c-2.21 0-4 1.79-4 4s1.79 4 4 4s4-1.79 4-4V7h4V3z"/></svg>',
41
+ Document: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8zm2 16H8v-2h8zm0-4H8v-2h8zm-3-5V3.5L18.5 9z"/></svg>',
42
+ Code: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6l6 6zm5.2 0l4.6-4.6l-4.6-4.6L166l6 6l-6 6z"/></svg>',
43
+
44
+ // UI Elements
45
+ Settings: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.49.49 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54A.48.48 0 0 0 13.94 2h-3.88a.48.48 0 0 0-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.49.49 0 0 0-.59.22L2.71 8.87a.49.49 0 0 0 .12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.47.41h3.88c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.470 .59-.22l1.92-3.32a.49.49 0 0 0-.12-.61zM12 15.6a3.6 3.6 0 1 1 0-7.2a3.6 3.6 0 0 1 0 7.2"/></svg>',
46
+ User: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4s-4 1.79-4 4s1.79 4 4 4m02c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4"/></svg>',
47
+ Heart: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5C2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3C19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54z"/></svg>',
48
+ Star: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2L9.19 8.63L2 9.24l5.464.73L5.82 21z"/></svg>',
49
+ Bell: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 22c1.1 0 2-.9 2-2h-4a2 2 0 0 0 2 2m6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 67.92 6 11v5l-2 2v1h16v-1z"/></svg>',
50
+ Calendar: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2m0 16H5V8h14z"/></svg>',
51
+ Clock: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8s8 3.58 8 8s-3.58 8-8 8m.5-13H11v6l5.253.15l.75-1.23l-4.5-2.67z"/></svg>',
52
+ Link: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M3.9 12c0-1.711.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M813h8v-2H8zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5"/></svg>',
53
+ Share: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M1816.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.51.25.81 2.04.81a33 0 0 0 0-6a3 3 0 0 0-33c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0 0 6c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65a2.92 2.92 0 1 0 2.92-2.92"/></svg>',
54
+ More: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2m12 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2m-6 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2"/></svg>',
55
+ ArrowUp: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m714l5-5l5 5z"/></svg>',
56
+ ArrowDown: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m7 10l5 5l5-5z"/></svg>',
57
+ ArrowLeft: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M14 7l-5 5l5 5z"/></svg>',
58
+ ArrowRight: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M10 17l5-5l-5-5z"/></svg>',
59
+ ChevronUp: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6l-6 6z"/></svg>',
60
+ ChevronDown: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6l-6-6z"/></svg>',
61
+ ChevronLeft: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M15.41 7.41L14 6l-6 6l6 6l1.41-1.41L10.83 12z"/></svg>',
62
+ ChevronRight: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M8.59 16.59L10 18l6-6l-6-6l-1.41 1.41L13.17 12z"/></svg>',
63
+
64
+ // Brands
65
+ GitHub: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.531.03 1.53 1.03c.87 1.522.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c00 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"/></svg>',
66
+ VSCode: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M17.583 2.403L12.598 7.14L7.614 3.028l-.995.613l4.05 3.485l-4.05 3.485l.995.613l4.984-4.111l4.9854.738l.994-.613l-4.05-3.485l4.05-3.486zM4.035 4.09v15.82l7.353.09V1zM19.965 1v22l-7.35-3.09V4.091z"/></svg>',
67
+ Chrome: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 20a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 5a5 5 0 0 0-5 5a5 5 0 0 0 5 5a5 5 0 0 0 5-5a5 5 0 0 0-5-5"/></svg>',
68
+ Slack: '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M4 4h16v16H4z"/></svg>',
69
+ } as const
package/index.ts CHANGED
@@ -1,14 +1,22 @@
1
1
  // export * from './auth' // Renderer-only, use @talex-touch/utils/renderer instead
2
+ export * from './account'
3
+ export * from './analytics'
2
4
  export * from './base'
3
5
  export * from './channel'
6
+ export * from './cloud-sync'
4
7
  export * from './common'
5
8
  export * from './core-box'
9
+ export * from './env'
6
10
  export * from './eventbus'
11
+ export * from './i18n'
12
+ export * from './icons'
7
13
  export * from './intelligence'
14
+ export * from './market'
15
+ export * from './permission'
8
16
  export * from './plugin'
9
17
  export * from './preload'
18
+ export * from './search'
10
19
  export * from './types'
11
20
  export * from './types/download'
12
21
  export * from './types/icon'
13
22
  export * from './types/update'
14
- export * from './market'
@@ -1,9 +1,28 @@
1
- import type { AiInvokeOptions, AiInvokeResult, AiProviderConfig } from '../types/intelligence'
1
+ import type {
2
+ IntelligenceInvokeOptions,
3
+ IntelligenceInvokeResult,
4
+ IntelligenceProviderConfig,
5
+ } from '../types/intelligence'
6
+ import type { ITuffTransport } from '../transport/types'
7
+ import {
8
+ createIntelligenceSdk,
9
+ type IntelligenceAuditLogEntry,
10
+ type IntelligenceAuditLogQueryOptions,
11
+ type IntelligenceChatRequest,
12
+ type IntelligenceCurrentUsage,
13
+ type IntelligenceQuotaCheckResult,
14
+ type IntelligenceQuotaConfig,
15
+ type IntelligenceSdk,
16
+ type IntelligenceSdkTransport,
17
+ type IntelligenceUsageSummary,
18
+ } from '../transport/sdk/domains/intelligence'
2
19
 
3
20
  export interface IntelligenceClientChannel {
4
- send: (eventName: string, payload: unknown) => Promise<any>
21
+ send: (eventName: string, payload?: unknown) => Promise<any>
5
22
  }
6
23
 
24
+ type IntelligenceChannelLike = IntelligenceClientChannel | ITuffTransport
25
+
7
26
  export type IntelligenceChannelResolver = () => IntelligenceClientChannel | null | undefined
8
27
 
9
28
  const defaultResolvers: IntelligenceChannelResolver[] = [
@@ -20,7 +39,9 @@ const defaultResolvers: IntelligenceChannelResolver[] = [
20
39
  },
21
40
  ]
22
41
 
23
- export function resolveIntelligenceChannel(resolvers: IntelligenceChannelResolver[] = defaultResolvers): IntelligenceClientChannel | null {
42
+ export function resolveIntelligenceChannel(
43
+ resolvers: IntelligenceChannelResolver[] = defaultResolvers,
44
+ ): IntelligenceClientChannel | null {
24
45
  for (const resolver of resolvers) {
25
46
  try {
26
47
  const channel = resolver()
@@ -35,53 +56,62 @@ export function resolveIntelligenceChannel(resolvers: IntelligenceChannelResolve
35
56
  return null
36
57
  }
37
58
 
38
- interface ChannelResponse<T> {
39
- ok: boolean
40
- result?: T
41
- error?: string
59
+ export interface IntelligenceClient extends IntelligenceSdk {
60
+ /**
61
+ * @deprecated 请优先使用 chatLangChain() 或 invoke('text.chat', ...)。
62
+ */
63
+ chat: (payload: IntelligenceChatRequest) => Promise<IntelligenceInvokeResult<string>>
64
+ }
65
+
66
+ function isTuffTransport(
67
+ channel: IntelligenceChannelLike | null | undefined,
68
+ ): channel is ITuffTransport {
69
+ return Boolean(channel && typeof (channel as ITuffTransport).stream === 'function')
42
70
  }
43
71
 
44
- async function assertResponse<T>(promise: Promise<ChannelResponse<T>>): Promise<T> {
45
- const response = await promise
46
- if (!response?.ok) {
47
- throw new Error(response?.error || 'Intelligence channel request failed')
72
+ function createChannelTransport(channel: IntelligenceClientChannel): IntelligenceSdkTransport {
73
+ return {
74
+ send: (event: { toEventName: () => string }, payload?: unknown) => channel.send(event.toEventName(), payload),
48
75
  }
49
- return response.result as T
50
76
  }
51
77
 
52
- export interface IntelligenceClient {
53
- invoke: <T = any>(capabilityId: string, payload: any, options?: AiInvokeOptions) => Promise<AiInvokeResult<T>>
54
- testProvider: (config: AiProviderConfig) => Promise<unknown>
55
- testCapability: (params: Record<string, any>) => Promise<unknown>
56
- fetchModels: (config: AiProviderConfig) => Promise<{ success: boolean, models?: string[], message?: string }>
78
+ function toClient(sdk: IntelligenceSdk): IntelligenceClient {
79
+ return {
80
+ ...sdk,
81
+ chat: payload => sdk.chatLangChain(payload),
82
+ }
57
83
  }
58
84
 
59
- export function createIntelligenceClient(channel?: IntelligenceClientChannel, resolvers?: IntelligenceChannelResolver[]): IntelligenceClient {
60
- const resolvedChannel = channel ?? resolveIntelligenceChannel(resolvers)
61
- if (!resolvedChannel) {
62
- throw new Error('[Intelligence Client] Unable to resolve channel. Pass a channel instance or register a resolver.')
85
+ export function createIntelligenceClient(
86
+ channel?: IntelligenceChannelLike,
87
+ resolvers?: IntelligenceChannelResolver[],
88
+ ): IntelligenceClient {
89
+ const resolved = channel ?? resolveIntelligenceChannel(resolvers)
90
+
91
+ if (!resolved) {
92
+ throw new Error(
93
+ '[Intelligence Client] Unable to resolve channel. Pass a channel instance or register a resolver.',
94
+ )
63
95
  }
64
96
 
65
- return {
66
- invoke<T = any>(capabilityId: string, payload: any, options?: AiInvokeOptions) {
67
- return assertResponse<AiInvokeResult<T>>(
68
- resolvedChannel.send('intelligence:invoke', { capabilityId, payload, options }),
69
- )
70
- },
71
- testProvider(config: AiProviderConfig) {
72
- return assertResponse(
73
- resolvedChannel.send('intelligence:test-provider', { provider: config }),
74
- )
75
- },
76
- testCapability(params: Record<string, any>) {
77
- return assertResponse(
78
- resolvedChannel.send('intelligence:test-capability', params),
79
- )
80
- },
81
- fetchModels(config: AiProviderConfig) {
82
- return assertResponse<{ success: boolean, models?: string[], message?: string }>(
83
- resolvedChannel.send('intelligence:fetch-models', { provider: config }),
84
- )
85
- },
97
+ if (isTuffTransport(resolved)) {
98
+ return toClient(createIntelligenceSdk(resolved))
86
99
  }
100
+
101
+ return toClient(createIntelligenceSdk(createChannelTransport(resolved)))
102
+ }
103
+
104
+ export type {
105
+ IntelligenceAuditLogEntry,
106
+ IntelligenceAuditLogQueryOptions,
107
+ IntelligenceCurrentUsage,
108
+ IntelligenceQuotaCheckResult,
109
+ IntelligenceQuotaConfig,
110
+ IntelligenceUsageSummary,
111
+ }
112
+
113
+ export type {
114
+ IntelligenceInvokeOptions,
115
+ IntelligenceInvokeResult,
116
+ IntelligenceProviderConfig,
87
117
  }
@@ -1,10 +1,11 @@
1
- import { StorageList } from '../common/storage/constants'
2
1
  import type {
3
2
  MarketProviderDefinition,
3
+ MarketProviderTrustLevel,
4
4
  MarketSourcesPayload,
5
5
  MarketSourcesStorageInfo,
6
- MarketProviderTrustLevel,
7
6
  } from './types'
7
+ import { StorageList } from '../common/storage/constants'
8
+ import { NEXUS_BASE_URL } from '../env'
8
9
 
9
10
  export const MARKET_SOURCES_STORAGE_KEY = StorageList.MARKET_SOURCES
10
11
  export const MARKET_SOURCES_STORAGE_VERSION = 1
@@ -21,15 +22,32 @@ function defineProvider(
21
22
  }
22
23
 
23
24
  export const DEFAULT_MARKET_PROVIDERS: MarketProviderDefinition[] = [
25
+ defineProvider({
26
+ id: 'tuff-nexus',
27
+ name: 'Tuff Nexus',
28
+ type: 'tpexApi',
29
+ url: NEXUS_BASE_URL,
30
+ description: 'Tuff 官方插件市场,提供经过审核的插件。',
31
+ enabled: true,
32
+ priority: 110,
33
+ trustLevel: 'official',
34
+ isOfficial: true,
35
+ readOnly: true,
36
+ config: {
37
+ apiUrl: `${NEXUS_BASE_URL}/api/market/plugins`,
38
+ },
39
+ }),
24
40
  defineProvider({
25
41
  id: 'talex-official',
26
42
  name: 'Talex Official',
27
43
  type: 'nexusStore',
28
44
  url: 'https://raw.githubusercontent.com/talex-touch/tuff-official-plugins/main/plugins.json',
29
45
  description: '官方插件市场,提供经过审核的核心插件。',
30
- enabled: true,
46
+ enabled: false,
31
47
  priority: 100,
32
48
  trustLevel: 'official',
49
+ isOfficial: true,
50
+ outdated: true,
33
51
  readOnly: true,
34
52
  config: {
35
53
  manifestUrl:
package/market/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './types'
2
1
  export * from './constants'
2
+ export * from './types'
package/market/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { StorageList } from '../common/storage/constants'
2
2
 
3
- export type MarketProviderType = 'repository' | 'nexusStore' | 'npmPackage'
3
+ export type MarketProviderType = 'repository' | 'nexusStore' | 'npmPackage' | 'tpexApi'
4
4
 
5
5
  export type MarketProviderTrustLevel = 'official' | 'verified' | 'unverified'
6
6
 
@@ -23,9 +23,17 @@ export interface MarketProviderDefinition {
23
23
  trustLevel?: MarketProviderTrustLevel
24
24
  tags?: string[]
25
25
  /**
26
- * Whether this provider should be treated as read-only (no install)
27
- */
26
+ * Whether this provider should be treated as read-only (no install)
27
+ */
28
28
  readOnly?: boolean
29
+ /**
30
+ * Whether this is an official provider
31
+ */
32
+ isOfficial?: boolean
33
+ /**
34
+ * Whether this provider is outdated and should be deprecated
35
+ */
36
+ outdated?: boolean
29
37
  }
30
38
 
31
39
  export interface MarketSourcesPayload {
@@ -36,8 +44,8 @@ export interface MarketSourcesPayload {
36
44
  sources: MarketProviderDefinition[]
37
45
  }
38
46
 
39
- export type MarketInstallInstruction =
40
- | {
47
+ export type MarketInstallInstruction
48
+ = | {
41
49
  type: 'url'
42
50
  url: string
43
51
  format?: 'zip' | 'tar' | 'tgz' | 'tpex'
@@ -64,7 +72,14 @@ export interface MarketPlugin {
64
72
  category?: string
65
73
  tags?: string[]
66
74
  author?: string
75
+ /**
76
+ * Icon class name (e.g., 'i-mdi-puzzle')
77
+ */
67
78
  icon?: string
79
+ /**
80
+ * Direct URL to icon image (e.g., '/api/images/xxx.svg')
81
+ */
82
+ iconUrl?: string
68
83
  metadata?: Record<string, unknown>
69
84
  readmeUrl?: string
70
85
  homepage?: string
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talex-touch/utils",
3
- "version": "1.0.40",
3
+ "version": "1.0.44",
4
4
  "private": false,
5
5
  "description": "Tuff series utils",
6
6
  "author": "TalexDreamSoul",
@@ -18,15 +18,25 @@
18
18
  "main": "index.ts",
19
19
  "module": "./index.ts",
20
20
  "scripts": {
21
+ "lint": "pnpm exec eslint --cache .",
22
+ "lint:fix": "pnpm exec eslint --cache --fix .",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "test:coverage": "vitest run --coverage",
21
26
  "publish": "npm publish --access public"
22
27
  },
23
28
  "peerDependencies": {
24
- "electron": "^37.2.4",
25
- "vue": "^3.5.15"
29
+ "electron": "^40.0.0",
30
+ "vue": "^3.5.27"
26
31
  },
27
32
  "dependencies": {
28
- "@vueuse/core": "^13.6.0",
33
+ "@vueuse/core": "^14.1.0",
34
+ "marked": "^17.0.1",
29
35
  "path-browserify": "^1.0.1",
30
- "vue": "^3.5.18"
36
+ "vue": "^3.5.27"
37
+ },
38
+ "devDependencies": {
39
+ "@vitest/coverage-v8": "^3.2.4",
40
+ "vitest": "^3.2.4"
31
41
  }
32
42
  }
@@ -1,49 +1,146 @@
1
- export interface Permission {
2
- /**
3
- * permission id
4
- */
5
- id: symbol
6
-
7
- /**
8
- * permission name
9
- */
10
- name: string
11
-
12
- /**
13
- * permission description
14
- */
15
- description: string
1
+ /**
2
+ * Permission Center
3
+ *
4
+ * Plugin permission management system.
5
+ */
6
+
7
+ import type { SdkApiVersion } from '../plugin'
8
+ import type {
9
+ ManifestPermissionReasons,
10
+ ManifestPermissions,
11
+ PluginPermissionStatus,
12
+ } from './types'
13
+ import {
14
+ checkSdkCompatibility,
15
+ CURRENT_SDK_VERSION,
16
+ } from '../plugin/sdk-version'
17
+ import {
18
+ DEFAULT_PERMISSIONS,
19
+ getPermissionIdCandidates,
20
+ normalizePermissionId,
21
+ permissionRegistry
22
+ } from './registry'
23
+
24
+ export * from './legacy'
25
+ export * from './registry'
26
+ export * from './types'
27
+
28
+ /**
29
+ * Parse permissions from manifest
30
+ */
31
+ export function parseManifestPermissions(manifest: {
32
+ permissions?: ManifestPermissions | string[]
33
+ permissionReasons?: ManifestPermissionReasons
34
+ }): { required: string[], optional: string[], reasons: ManifestPermissionReasons } {
35
+ let required: string[] = []
36
+ let optional: string[] = []
37
+
38
+ if (Array.isArray(manifest.permissions)) {
39
+ // Legacy format: string[]
40
+ required = manifest.permissions
41
+ }
42
+ else if (manifest.permissions) {
43
+ // New format: { required, optional }
44
+ required = manifest.permissions.required || []
45
+ optional = manifest.permissions.optional || []
46
+ }
47
+
48
+ // Validate permission IDs
49
+ required = required
50
+ .map(id => normalizePermissionId(id))
51
+ .filter(id => permissionRegistry.has(id))
52
+ optional = optional
53
+ .map(id => normalizePermissionId(id))
54
+ .filter(id => permissionRegistry.has(id))
55
+
56
+ return {
57
+ required,
58
+ optional,
59
+ reasons: manifest.permissionReasons || {},
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get plugin permission status
65
+ */
66
+ export function getPluginPermissionStatus(
67
+ pluginId: string,
68
+ sdkapi: SdkApiVersion | undefined,
69
+ declaredPermissions: { required: string[], optional: string[] },
70
+ grantedPermissions: string[],
71
+ ): PluginPermissionStatus {
72
+ const sdkCompat = checkSdkCompatibility(sdkapi, pluginId)
73
+ const required = [...new Set(declaredPermissions.required.map(id => normalizePermissionId(id)))]
74
+ const optional = [...new Set(declaredPermissions.optional.map(id => normalizePermissionId(id)))]
75
+ const granted = [...new Set(grantedPermissions.map(id => normalizePermissionId(id)))]
76
+ const defaultPermissions = [...new Set(DEFAULT_PERMISSIONS.map(id => normalizePermissionId(id)))]
77
+
78
+ // Calculate missing required permissions
79
+ const missingRequired = required.filter(
80
+ p => !granted.includes(p) && !defaultPermissions.includes(p),
81
+ )
82
+
83
+ // Calculate denied (not in granted and not default)
84
+ const allDeclared = [...required, ...optional]
85
+ const denied = allDeclared.filter(
86
+ p => !granted.includes(p) && !defaultPermissions.includes(p),
87
+ )
88
+
89
+ return {
90
+ pluginId,
91
+ sdkapi,
92
+ enforcePermissions: sdkCompat.enforcePermissions,
93
+ required,
94
+ optional,
95
+ granted: [...new Set([...granted, ...defaultPermissions])],
96
+ denied,
97
+ missingRequired,
98
+ warning: sdkCompat.warning,
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Check if plugin has permission
104
+ */
105
+ export function hasPermission(
106
+ status: PluginPermissionStatus,
107
+ permissionId: string,
108
+ ): boolean {
109
+ // If enforcement is disabled, allow all
110
+ if (!status.enforcePermissions) {
111
+ return true
112
+ }
113
+
114
+ // Check if granted
115
+ const candidates = getPermissionIdCandidates(permissionId)
116
+ return candidates.some(id => status.granted.includes(id))
16
117
  }
17
118
 
18
- export interface IPermissionCenter {
19
- /**
20
- * add a permission
21
- * @param pluginScope plugin name
22
- * @param permission permission
23
- * @throws if permission already exists
24
- */
25
- addPermission: (pluginScope: string, permission: Permission) => void
26
-
27
- /**
28
- * remove a permission
29
- * @param pluginScope plugin name
30
- * @param permission permission
31
- * @throws if permission not exists
32
- */
33
- delPermission: (pluginScope: string, permission: Permission) => void
34
-
35
- /**
36
- * if pluginScope has permission
37
- * @param pluginScope plugin name
38
- * @param permission permission
39
- */
40
- hasPermission: (pluginScope: string, permission: Permission) => boolean
41
-
42
- /**
43
- * get permission
44
- * @param pluginScope plugin name
45
- * @param permission permission id
46
- * @returns permission
47
- */
48
- getPermission: (pluginScope: string, permission: symbol) => Permission
119
+ /**
120
+ * Generate permission issue for plugin
121
+ */
122
+ export function generatePermissionIssue(
123
+ status: PluginPermissionStatus,
124
+ ): { type: 'error' | 'warning', message: string, code: string, suggestion?: string } | null {
125
+ // SDK version warning
126
+ if (status.warning && !status.enforcePermissions) {
127
+ return {
128
+ type: 'warning',
129
+ message: status.warning,
130
+ code: status.sdkapi === undefined ? 'SDK_VERSION_MISSING' : 'SDK_VERSION_OUTDATED',
131
+ suggestion: `Add "sdkapi": ${CURRENT_SDK_VERSION} to manifest.json for permission enforcement.`,
132
+ }
133
+ }
134
+
135
+ // Missing required permissions (warning, not error - plugin can still run)
136
+ if (status.enforcePermissions && status.missingRequired.length > 0) {
137
+ return {
138
+ type: 'warning',
139
+ message: `Missing required permissions: ${status.missingRequired.join(', ')}`,
140
+ code: 'PERMISSION_MISSING',
141
+ suggestion: 'Grant permissions in Plugin Details > Permissions tab.',
142
+ }
143
+ }
144
+
145
+ return null
49
146
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Legacy Permission Types
3
+ *
4
+ * For backward compatibility with old permission-center.ts
5
+ * @deprecated Use new permission system instead
6
+ */
7
+
8
+ /**
9
+ * Legacy permission interface
10
+ */
11
+ export interface Permission {
12
+ id: symbol
13
+ name: string
14
+ description?: string
15
+ }
16
+
17
+ /**
18
+ * Legacy permission center interface
19
+ */
20
+ export interface IPermissionCenter {
21
+ addPermission: (pluginScope: string, permission: Permission) => void
22
+ delPermission: (pluginScope: string, permission: Permission) => void
23
+ hasPermission: (pluginScope: string, permission: Permission) => boolean
24
+ getPermission: (pluginScope: string, permission: symbol) => Permission
25
+ save: () => Promise<void>
26
+ }