@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
@@ -1,5 +1,6 @@
1
1
  import type { FileDetails, StorageStats, StorageTreeNode } from '../../types/storage'
2
2
  import { ensureRendererChannel } from './channel'
3
+ import { usePluginName } from './plugin-info'
3
4
 
4
5
  /**
5
6
  * Get the storage for the current plugin.
@@ -9,12 +10,7 @@ import { ensureRendererChannel } from './channel'
9
10
  * @returns An object with methods to interact with the storage.
10
11
  */
11
12
  export function usePluginStorage() {
12
- // @ts-ignore
13
- const pluginName = window.$plugin.name as string
14
-
15
- if (!pluginName) {
16
- throw new Error('[Plugin SDK] Cannot determine plugin name. Make sure this is called in a plugin context.')
17
- }
13
+ const pluginName = usePluginName('[Plugin SDK] Cannot determine plugin name. Make sure this is called in a plugin context.')
18
14
 
19
15
  const channel = ensureRendererChannel('[Plugin Storage] Channel not available. Make sure this is called in a plugin context.')
20
16
 
@@ -1,14 +1,7 @@
1
1
  import type { ActiveAppSnapshot } from './types'
2
-
3
- function ensurePluginChannel() {
4
- const channel = (window as any)?.$channel
5
- if (!channel) {
6
- throw new Error('[Plugin SDK] System channel requires plugin renderer context with $channel available.')
7
- }
8
- return channel
9
- }
2
+ import { useChannel } from './channel'
10
3
 
11
4
  export async function getActiveAppSnapshot(options: { forceRefresh?: boolean } = {}): Promise<ActiveAppSnapshot | null> {
12
- const channel = ensurePluginChannel()
5
+ const channel = useChannel('[Plugin SDK] System channel requires plugin renderer context with $channel available.')
13
6
  return channel.send('system:get-active-app', options)
14
7
  }
@@ -0,0 +1,41 @@
1
+ import { useChannel } from './channel'
2
+
3
+ export interface TempPluginFileCreateOptions {
4
+ ext?: string
5
+ text?: string
6
+ base64?: string
7
+ prefix?: string
8
+ /**
9
+ * Optional retention in milliseconds.
10
+ * If omitted, the host will apply a default plugin temp retention policy.
11
+ */
12
+ retentionMs?: number
13
+ }
14
+
15
+ export interface TempPluginFileResult {
16
+ url: string
17
+ sizeBytes: number
18
+ createdAt: number
19
+ }
20
+
21
+ export function useTempPluginFiles() {
22
+ const channel = useChannel('[Plugin SDK] Temp files require plugin renderer context with $channel available.')
23
+
24
+ return {
25
+ async create(options: TempPluginFileCreateOptions): Promise<TempPluginFileResult> {
26
+ const res = await channel.send('temp-file:create', options ?? {})
27
+ if (!res || typeof res !== 'object') {
28
+ throw new Error('[Plugin SDK] temp-file:create returned invalid response')
29
+ }
30
+ return res as TempPluginFileResult
31
+ },
32
+
33
+ async delete(url: string): Promise<boolean> {
34
+ const res = await channel.send('temp-file:delete', { url })
35
+ if (res && typeof res === 'object' && 'success' in res) {
36
+ return Boolean((res as any).success)
37
+ }
38
+ return Boolean(res)
39
+ },
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ import type { ITouchSDK } from './index'
2
+ import { hasWindow } from '../../env'
3
+
4
+ const DEFAULT_TOUCH_SDK_ERROR
5
+ = '[TouchSDK] Touch SDK not available. Make sure this is called in a plugin context.'
6
+
7
+ let cachedTouchSDK: ITouchSDK | null = null
8
+
9
+ export function useTouchSDK(errorMessage: string = DEFAULT_TOUCH_SDK_ERROR): ITouchSDK {
10
+ const globalWindow = hasWindow() ? window : undefined
11
+ const windowSdk = (globalWindow as any)?.$touchSDK as ITouchSDK | undefined
12
+ const sdk = windowSdk ?? cachedTouchSDK
13
+ if (!sdk) {
14
+ throw new Error(errorMessage)
15
+ }
16
+ cachedTouchSDK = sdk
17
+ return sdk
18
+ }
@@ -6,6 +6,7 @@
6
6
 
7
7
  import type { ITouchChannel, ITouchClientChannel, StandardChannelData } from '@talex-touch/utils/channel'
8
8
  import type { IPluginFeature } from '../index'
9
+ import path from 'node:path'
9
10
 
10
11
  /**
11
12
  * Handler signature for plugin channel events.
@@ -90,6 +91,15 @@ export interface IPluginRendererChannel {
90
91
  export interface PluginClipboardItem {
91
92
  id?: number
92
93
  type: 'text' | 'image' | 'files'
94
+ /**
95
+ * Clipboard content:
96
+ * - text: plain string
97
+ * - files: JSON string array
98
+ * - image: defaults to a small preview data URL to keep IPC payload light
99
+ *
100
+ * For images, the original asset URL (tfile://...) may be available at:
101
+ * - `meta.image_original_url`
102
+ */
93
103
  content: string
94
104
  thumbnail?: string | null
95
105
  rawContent?: string | null
@@ -144,7 +154,6 @@ export interface PluginClipboardSearchResponse {
144
154
  pageSize: number
145
155
  }
146
156
 
147
-
148
157
  export interface ActiveAppSnapshot {
149
158
  identifier: string | null
150
159
  displayName: string | null
@@ -230,6 +239,24 @@ export interface IPluginUtils {
230
239
  */
231
240
  feature: import('./feature-sdk').FeatureSDK
232
241
 
242
+ /**
243
+ * MetaOverlay SDK for registering global actions
244
+ * @see {@link MetaSDK}
245
+ */
246
+ meta: import('./meta-sdk').MetaSDK
247
+
248
+ /**
249
+ * Power SDK for low power status
250
+ * @see {@link PowerSDK}
251
+ */
252
+ power: import('./power').PowerSDK
253
+
254
+ /**
255
+ * Recommend SDK for registering custom recommendation providers
256
+ * @see {@link RecommendSDK}
257
+ */
258
+ recommend: import('./recommend').RecommendSDK
259
+
233
260
  /**
234
261
  * Opens a URL in the default browser
235
262
  * @param url - The URL to open
@@ -496,14 +523,14 @@ export interface IEventManager {
496
523
  * @param event - The event name to listen for
497
524
  * @param callback - The callback function to execute when event is emitted
498
525
  */
499
- on: (event: string, callback: Function) => void
526
+ on: (event: string, callback: PluginEventHandler) => void
500
527
 
501
528
  /**
502
529
  * Removes an event listener
503
530
  * @param event - The event name to stop listening for
504
531
  * @param callback - The callback function to remove
505
532
  */
506
- off: (event: string, callback: Function) => void
533
+ off: (event: string, callback: PluginEventHandler) => void
507
534
 
508
535
  /**
509
536
  * Emits an event with optional arguments
@@ -513,6 +540,8 @@ export interface IEventManager {
513
540
  emit: (event: string, ...args: any[]) => void
514
541
  }
515
542
 
543
+ export type PluginEventHandler = (...args: any[]) => void
544
+
516
545
  /**
517
546
  * Plugin configuration interface
518
547
  *
@@ -644,7 +673,6 @@ export function createStorageManager(
644
673
  pluginPath: string,
645
674
  fse: any,
646
675
  ): IStorageManager {
647
- const path = require('node:path')
648
676
  const dataPath = path.join(pluginPath, 'data')
649
677
 
650
678
  /**
@@ -954,6 +982,18 @@ export interface TriggerFeatureRequest {
954
982
  query?: string
955
983
  }
956
984
 
985
+ /**
986
+ * Register a widget for preview or rendering
987
+ */
988
+ export interface RegisterWidgetRequest {
989
+ /** Plugin name */
990
+ plugin: string
991
+ /** Feature ID */
992
+ feature: string
993
+ /** Emit update event even if cached */
994
+ emitAsUpdate?: boolean
995
+ }
996
+
957
997
  /**
958
998
  * Input changed event payload
959
999
  */
@@ -3,28 +3,31 @@ import type {
3
3
  BrowserWindowConstructorOptions,
4
4
  WebContents,
5
5
  } from 'electron'
6
- import { genChannel } from '../../channel'
6
+ import { useChannel } from '../channel'
7
7
 
8
- export function createWindow(options: BrowserWindowConstructorOptions & { file?: string } & { url?: string }): number {
9
- const res = genChannel().sendSync('window:new', options)
8
+ export async function createWindow(
9
+ options: BrowserWindowConstructorOptions & { file?: string } & { url?: string },
10
+ ): Promise<number> {
11
+ const channel = useChannel('[Plugin SDK] Window creation requires renderer channel.')
12
+ const res = await channel.send('window:new', options)
10
13
  if (res.error)
11
14
  throw new Error(res.error)
12
15
 
13
16
  return res.id
14
17
  }
15
18
 
16
- export function toggleWinVisible(id: number, visible?: boolean): boolean {
17
- const res = genChannel().sendSync('window:visible', visible !== undefined ? { id, visible } : { id })
19
+ export async function toggleWinVisible(id: number, visible?: boolean): Promise<boolean> {
20
+ const channel = useChannel('[Plugin SDK] Window visibility requires renderer channel.')
21
+ const res = await channel.send('window:visible', visible !== undefined ? { id, visible } : { id })
18
22
  if (res.error)
19
23
  throw new Error(res.error)
20
24
 
21
25
  return res.visible
22
26
  }
23
27
 
24
- export function setWindowProperty(id: number, property: {
25
-
26
- }): boolean {
27
- const res = genChannel().sendSync('window:property', { id, property })
28
+ export async function setWindowProperty(id: number, property: WindowProperties): Promise<boolean> {
29
+ const channel = useChannel('[Plugin SDK] Window property requires renderer channel.')
30
+ const res = await channel.send('window:property', { id, property })
28
31
  if (res.error)
29
32
  throw new Error(res.error)
30
33
 
@@ -0,0 +1,231 @@
1
+ import type { SdkApiVersion } from './index'
2
+
3
+ /**
4
+ * Known SDK API versions (format: YYMMDD).
5
+ *
6
+ * Ranges (rough):
7
+ * - < 251212: legacy mode (no permission enforcement, no category requirement)
8
+ * - 251212 ~ 260113: permission enforcement + new input model baseline
9
+ * - >= 260114: `manifest.json.category` is required for plugin grouping
10
+ * - >= 260121: `tfileScope` is required when requesting tfile access
11
+ * - >= 260215: plugin sqlite sdk is available
12
+ */
13
+ export enum SdkApi {
14
+ /**
15
+ * 2025-12-12: permissions + input model baseline.
16
+ */
17
+ V251212 = 251212,
18
+ /**
19
+ * 2026-01-14: require `manifest.json.category` for plugins.
20
+ */
21
+ V260114 = 260114,
22
+ /**
23
+ * 2026-01-21: add tfile permission + scope enforcement.
24
+ */
25
+ V260121 = 260121,
26
+ /**
27
+ * 2026-02-15: add plugin sqlite sdk support.
28
+ */
29
+ V260215 = 260215,
30
+ }
31
+
32
+ /**
33
+ * Supported SDK versions in descending order.
34
+ * Used to gracefully fallback for unknown/invalid sdkapi values.
35
+ */
36
+ export const SUPPORTED_SDK_VERSIONS: readonly SdkApiVersion[] = [
37
+ SdkApi.V260215,
38
+ SdkApi.V260121,
39
+ SdkApi.V260114,
40
+ SdkApi.V251212,
41
+ ]
42
+
43
+ /**
44
+ * Current SDK API version.
45
+ * Updated when breaking changes are introduced to plugin APIs.
46
+ */
47
+ export const CURRENT_SDK_VERSION: SdkApiVersion = SdkApi.V260215
48
+
49
+ /**
50
+ * Minimum SDK version required for permission enforcement.
51
+ * Plugins below this version will bypass permission checks with a warning.
52
+ */
53
+ export const PERMISSION_ENFORCEMENT_MIN_VERSION: SdkApiVersion = SdkApi.V251212
54
+
55
+ /**
56
+ * Minimum SDK version required for `manifest.json.category`.
57
+ */
58
+ export const CATEGORY_REQUIRED_MIN_VERSION: SdkApiVersion = SdkApi.V260114
59
+
60
+ /**
61
+ * Minimum SDK version required for `tfileScope` enforcement.
62
+ */
63
+ export const TFILE_SCOPE_REQUIRED_MIN_VERSION: SdkApiVersion = SdkApi.V260121
64
+
65
+ /**
66
+ * SDK version compatibility result
67
+ */
68
+ export interface SdkCompatibilityResult {
69
+ /** Whether the plugin SDK version is compatible */
70
+ compatible: boolean
71
+ /** Whether permission enforcement should be applied */
72
+ enforcePermissions: boolean
73
+ /** Warning message if compatibility issues exist */
74
+ warning?: string
75
+ /** Suggestion for fixing compatibility issues */
76
+ suggestion?: string
77
+ }
78
+
79
+ /**
80
+ * Check SDK version compatibility for a plugin.
81
+ * @param pluginSdkVersion - The sdkapi value from plugin manifest (undefined if not declared)
82
+ * @param pluginName - Plugin name for error messages
83
+ * @returns Compatibility check result
84
+ */
85
+ export function checkSdkCompatibility(
86
+ pluginSdkVersion: SdkApiVersion | undefined,
87
+ pluginName: string,
88
+ ): SdkCompatibilityResult {
89
+ // No sdkapi declared - legacy plugin
90
+ if (pluginSdkVersion === undefined) {
91
+ return {
92
+ compatible: true,
93
+ enforcePermissions: false,
94
+ warning: `Plugin "${pluginName}" does not declare sdkapi version. Permission enforcement is disabled for compatibility.`,
95
+ suggestion: `Add "sdkapi": ${CURRENT_SDK_VERSION} to manifest.json to enable permission enforcement.`,
96
+ }
97
+ }
98
+
99
+ const resolved = resolveSdkApiVersion(pluginSdkVersion)
100
+ const warningParts: string[] = []
101
+ const suggestionParts: string[] = []
102
+
103
+ // Validate + normalize to a supported SDK version (graceful fallback)
104
+ if (resolved === undefined) {
105
+ return {
106
+ compatible: true,
107
+ enforcePermissions: false,
108
+ warning: `Plugin "${pluginName}" has invalid sdkapi value: ${pluginSdkVersion}. Falling back to legacy mode.`,
109
+ suggestion: `Use format YYMMDD (e.g., "sdkapi": ${CURRENT_SDK_VERSION}).`,
110
+ }
111
+ }
112
+
113
+ if (resolved !== pluginSdkVersion) {
114
+ warningParts.push(
115
+ `Plugin "${pluginName}" declares sdkapi ${pluginSdkVersion}, but it is not a supported SDK marker. Falling back to ${resolved}.`,
116
+ )
117
+ suggestionParts.push(`Use a supported sdkapi marker, e.g., ${CURRENT_SDK_VERSION}.`)
118
+ }
119
+
120
+ // Version too old - bypass permissions with warning
121
+ if (resolved < PERMISSION_ENFORCEMENT_MIN_VERSION) {
122
+ return {
123
+ compatible: true,
124
+ enforcePermissions: false,
125
+ warning: [
126
+ ...warningParts,
127
+ `Plugin "${pluginName}" uses legacy SDK version ${resolved}. Permission enforcement is disabled.`,
128
+ ].join(' '),
129
+ suggestion: [
130
+ ...suggestionParts,
131
+ `Update to sdkapi: ${CURRENT_SDK_VERSION} for full permission support.`,
132
+ ].join(' '),
133
+ }
134
+ }
135
+
136
+ // Version newer than current - might use unsupported features
137
+ if (pluginSdkVersion > CURRENT_SDK_VERSION) {
138
+ return {
139
+ compatible: true,
140
+ enforcePermissions: true,
141
+ warning: [
142
+ ...warningParts,
143
+ `Plugin "${pluginName}" requires SDK version ${pluginSdkVersion}, but current version is ${CURRENT_SDK_VERSION}. Some features may not work.`,
144
+ ].join(' '),
145
+ suggestion: [
146
+ ...suggestionParts,
147
+ `Update Tuff to the latest version for full compatibility.`,
148
+ ].join(' '),
149
+ }
150
+ }
151
+
152
+ // Perfect match or compatible older version
153
+ return {
154
+ compatible: true,
155
+ enforcePermissions: true,
156
+ warning: warningParts.length ? warningParts.join(' ') : undefined,
157
+ suggestion: suggestionParts.length ? suggestionParts.join(' ') : undefined,
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Resolve a plugin-declared sdkapi to the nearest supported SDK marker.
163
+ *
164
+ * Rules:
165
+ * - Invalid values => undefined (legacy)
166
+ * - Unknown future versions => fallback to the latest supported <= declared
167
+ * - Known versions => keep as-is
168
+ */
169
+ export function resolveSdkApiVersion(raw: unknown): SdkApiVersion | undefined {
170
+ const num
171
+ = typeof raw === 'number'
172
+ ? raw
173
+ : typeof raw === 'string'
174
+ ? parseSdkVersion(raw)
175
+ : undefined
176
+
177
+ if (num === undefined || !isValidSdkVersion(num)) {
178
+ return undefined
179
+ }
180
+
181
+ for (const v of SUPPORTED_SDK_VERSIONS) {
182
+ if (num >= v) {
183
+ return v
184
+ }
185
+ }
186
+
187
+ return undefined
188
+ }
189
+
190
+ /**
191
+ * Validate SDK version format (YYMMDD)
192
+ */
193
+ export function isValidSdkVersion(version: number): boolean {
194
+ if (!Number.isInteger(version) || version < 100000 || version > 999999) {
195
+ return false
196
+ }
197
+
198
+ const str = version.toString()
199
+ const year = Number.parseInt(str.substring(0, 2), 10)
200
+ const month = Number.parseInt(str.substring(2, 4), 10)
201
+ const day = Number.parseInt(str.substring(4, 6), 10)
202
+
203
+ // Basic validation: year 20-99, month 01-12, day 01-31
204
+ return year >= 20 && year <= 99 && month >= 1 && month <= 12 && day >= 1 && day <= 31
205
+ }
206
+
207
+ /**
208
+ * Format SDK version for display
209
+ * @param version - SDK version number (YYMMDD)
210
+ * @returns Formatted string like "25.12.12"
211
+ */
212
+ export function formatSdkVersion(version: SdkApiVersion): string {
213
+ const str = version.toString().padStart(6, '0')
214
+ return `${str.substring(0, 2)}.${str.substring(2, 4)}.${str.substring(4, 6)}`
215
+ }
216
+
217
+ /**
218
+ * Parse SDK version from string
219
+ * @param str - Version string like "251212" or "25.12.12"
220
+ * @returns SDK version number or undefined if invalid
221
+ */
222
+ export function parseSdkVersion(str: string): SdkApiVersion | undefined {
223
+ // Remove dots if present
224
+ const cleaned = str.replace(/\./g, '')
225
+ const num = Number.parseInt(cleaned, 10)
226
+
227
+ if (isValidSdkVersion(num)) {
228
+ return num
229
+ }
230
+ return undefined
231
+ }
@@ -1,7 +1,8 @@
1
1
  import type { LoadingEvent, LoadingMode, LoadingState, PreloadAPI } from './loading'
2
+ import { hasWindow } from '../env'
2
3
 
3
4
  function getPreloadApi(): PreloadAPI | null {
4
- if (typeof window === 'undefined')
5
+ if (!hasWindow())
5
6
  return null
6
7
  return (window as any).api ?? null
7
8
  }
@@ -37,7 +38,7 @@ export function preloadDebugStep(message: string, delta = 0.08): void {
37
38
  }
38
39
 
39
40
  export function preloadRemoveOverlay(): void {
40
- if (typeof window === 'undefined')
41
+ if (!hasWindow())
41
42
  return
42
43
  window.postMessage({ payload: 'removeLoading' }, '*')
43
44
  }
@@ -5,6 +5,10 @@
5
5
  export interface IArgMapperOptions {
6
6
  /** The type of touch window - either main window or core-box popup */
7
7
  touchType?: 'main' | 'core-box'
8
+ /** The sub-type for core-box windows (e.g., division-box) */
9
+ coreType?: 'division-box'
10
+ /** Whether this is a meta-overlay WebContentsView */
11
+ metaOverlay?: 'true' | 'false'
8
12
  /** User data directory path */
9
13
  userDataDir?: string
10
14
  /** Application path */
@@ -31,23 +35,21 @@ declare global {
31
35
  * @param args - Array of command line arguments (defaults to process.argv)
32
36
  * @returns Mapped command line arguments as key-value pairs
33
37
  */
34
- export function useArgMapper(args: string[] = process.argv): IArgMapperOptions {
35
- if (window.$argMapper) {
38
+ export function useArgMapper(args: string[] = (globalThis as any)?.process?.argv ?? []): IArgMapperOptions {
39
+ if (window.$argMapper)
36
40
  return window.$argMapper
37
- }
38
41
 
39
42
  const mapper: IArgMapperOptions = {}
40
-
41
43
  for (const arg of args) {
42
44
  if (arg.startsWith('--') && arg.includes('=')) {
43
45
  const [key, ...valueParts] = arg.slice(2).split('=')
44
46
  const value = valueParts.join('=')
45
-
47
+ if (!key)
48
+ continue
46
49
  const camelCaseKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
47
50
  mapper[camelCaseKey] = value
48
51
  }
49
52
  }
50
-
51
53
  return window.$argMapper = mapper
52
54
  }
53
55
 
@@ -76,3 +78,29 @@ export function isMainWindow() {
76
78
  export function isCoreBox() {
77
79
  return useTouchType() === 'core-box'
78
80
  }
81
+
82
+ /**
83
+ * Gets the core-box sub-type from command line arguments
84
+ * @returns The core type ('division-box') or undefined
85
+ */
86
+ export function useCoreType() {
87
+ const argMapper = useArgMapper()
88
+ return argMapper.coreType
89
+ }
90
+
91
+ /**
92
+ * Checks if the current window is a division-box window
93
+ * @returns True if the current window is a division-box
94
+ */
95
+ export function isDivisionBox() {
96
+ return isCoreBox() && useCoreType() === 'division-box'
97
+ }
98
+
99
+ /**
100
+ * Checks if the current window is a meta-overlay WebContentsView
101
+ * @returns True if the current window is a meta-overlay
102
+ */
103
+ export function isMetaOverlay() {
104
+ const argMapper = useArgMapper()
105
+ return argMapper.metaOverlay === 'true'
106
+ }
@@ -1,5 +1,18 @@
1
1
  export * from './arg-mapper'
2
2
  export * from './initialize'
3
3
  export * from './performance'
4
+ export * from './use-agent-market-sdk'
5
+ export * from './use-agents-sdk'
6
+ export * from './use-app-sdk'
4
7
  export * from './use-channel'
8
+ export * from './use-download-sdk'
5
9
  export * from './use-intelligence'
10
+ export * from './use-intelligence-sdk'
11
+ export * from './use-intelligence-stats'
12
+ export * from './use-market-sdk'
13
+ export * from './use-notification-sdk'
14
+ export * from './use-permission-sdk'
15
+ export * from './use-platform-sdk'
16
+ export * from './use-plugin-sdk'
17
+ export * from './use-settings-sdk'
18
+ export * from './use-update-sdk'
@@ -102,12 +102,13 @@ export function useInitialize(): IInitializationInfo {
102
102
  }
103
103
 
104
104
  const now = Date.now()
105
+ const runtimePlatform = (globalThis as any)?.process?.platform ?? navigator.platform
105
106
  const initInfo: IInitializationInfo = {
106
107
  initTimestamp: now,
107
108
  initTime: new Date(now).toISOString(),
108
109
  userAgent: navigator.userAgent,
109
110
  currentUrl: window.location.href,
110
- platform: process.platform,
111
+ platform: runtimePlatform,
111
112
  screenResolution: {
112
113
  width: screen.width,
113
114
  height: screen.height,
@@ -0,0 +1,7 @@
1
+ import { useTuffTransport } from '../../transport'
2
+ import { createAgentMarketSdk } from '../../transport/sdk/domains/agents-market'
3
+
4
+ export function useAgentMarketSdk() {
5
+ const transport = useTuffTransport()
6
+ return createAgentMarketSdk(transport)
7
+ }