@talex-touch/utils 1.0.30 → 1.0.32

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 (113) hide show
  1. package/animation/window-node.ts +205 -0
  2. package/animation/window.ts +19 -15
  3. package/auth/clerk-types.ts +1 -1
  4. package/auth/index.ts +1 -1
  5. package/auth/useAuthState.ts +6 -5
  6. package/auth/useClerkConfig.ts +6 -6
  7. package/auth/useClerkProvider.ts +3 -2
  8. package/channel/index.ts +28 -21
  9. package/common/file-scan-constants.ts +137 -121
  10. package/common/file-scan-utils.ts +49 -25
  11. package/common/index.ts +3 -3
  12. package/common/search/gather.ts +1 -1
  13. package/common/search/index.ts +5 -6
  14. package/common/storage/constants.ts +3 -2
  15. package/common/storage/entity/app-settings.ts +19 -3
  16. package/common/storage/entity/shortcut-settings.ts +10 -10
  17. package/common/storage/shortcut-storage.ts +6 -4
  18. package/common/utils/file.ts +15 -4
  19. package/common/utils/index.ts +62 -52
  20. package/common/utils/polling.ts +114 -63
  21. package/common/utils/task-queue.ts +11 -10
  22. package/common/utils/time.ts +50 -47
  23. package/common/utils/timing.ts +41 -37
  24. package/core-box/builder/index.ts +1 -1
  25. package/core-box/builder/tuff-builder.ts +255 -230
  26. package/core-box/index.ts +3 -6
  27. package/core-box/preview/index.ts +1 -0
  28. package/core-box/preview/types.ts +43 -0
  29. package/core-box/tuff/index.ts +1 -1
  30. package/core-box/tuff/tuff-dsl.ts +419 -253
  31. package/electron/clipboard-helper.ts +20 -12
  32. package/electron/download-manager.ts +43 -42
  33. package/electron/env-tool.ts +19 -18
  34. package/electron/file-parsers/index.ts +2 -2
  35. package/electron/file-parsers/parsers/text-parser.ts +15 -14
  36. package/electron/file-parsers/registry.ts +9 -7
  37. package/electron/file-parsers/types.ts +4 -4
  38. package/electron/index.ts +1 -1
  39. package/eventbus/index.ts +11 -11
  40. package/index.ts +6 -5
  41. package/intelligence/client.ts +87 -0
  42. package/intelligence/index.ts +1 -0
  43. package/package.json +14 -14
  44. package/permission/index.ts +8 -8
  45. package/plugin/channel.ts +77 -68
  46. package/plugin/index.ts +113 -84
  47. package/plugin/install.ts +8 -8
  48. package/plugin/log/types.ts +5 -5
  49. package/plugin/node/index.ts +1 -1
  50. package/plugin/node/logger-manager.ts +14 -11
  51. package/plugin/node/logger.ts +8 -8
  52. package/plugin/plugin-source.ts +11 -11
  53. package/plugin/preload.ts +6 -3
  54. package/plugin/providers/registry.ts +8 -7
  55. package/plugin/providers/types.ts +6 -6
  56. package/plugin/sdk/channel.ts +20 -20
  57. package/plugin/sdk/clipboard.ts +8 -6
  58. package/plugin/sdk/common.ts +10 -6
  59. package/plugin/sdk/core-box.ts +2 -3
  60. package/plugin/sdk/division-box.ts +266 -0
  61. package/plugin/sdk/enum/bridge-event.ts +1 -1
  62. package/plugin/sdk/examples/storage-onDidChange-example.js +1 -1
  63. package/plugin/sdk/features.ts +34 -26
  64. package/plugin/sdk/hooks/bridge.ts +3 -6
  65. package/plugin/sdk/hooks/index.ts +1 -1
  66. package/plugin/sdk/hooks/life-cycle.ts +4 -10
  67. package/plugin/sdk/index.ts +9 -13
  68. package/plugin/sdk/service/index.ts +3 -3
  69. package/plugin/sdk/storage.ts +4 -4
  70. package/plugin/sdk/system.ts +1 -1
  71. package/plugin/sdk/types.ts +169 -143
  72. package/plugin/sdk/window/index.ts +8 -5
  73. package/preload/loading.ts +6 -6
  74. package/preload/renderer.ts +4 -2
  75. package/renderer/hooks/arg-mapper.ts +1 -2
  76. package/renderer/hooks/index.ts +2 -0
  77. package/renderer/hooks/initialize.ts +10 -8
  78. package/renderer/hooks/performance.ts +4 -4
  79. package/renderer/hooks/use-channel.ts +150 -0
  80. package/renderer/hooks/use-intelligence.ts +236 -0
  81. package/renderer/index.ts +6 -1
  82. package/renderer/ref.ts +32 -36
  83. package/renderer/slots.ts +29 -26
  84. package/renderer/storage/app-settings.ts +16 -6
  85. package/renderer/storage/base-storage.ts +236 -88
  86. package/renderer/storage/index.ts +3 -0
  87. package/renderer/storage/intelligence-storage.ts +215 -0
  88. package/renderer/storage/openers.ts +13 -3
  89. package/renderer/touch-sdk/env.ts +41 -41
  90. package/renderer/touch-sdk/index.ts +1 -1
  91. package/renderer/touch-sdk/terminal.ts +5 -5
  92. package/renderer/touch-sdk/utils.ts +4 -3
  93. package/search/levenshtein-utils.ts +11 -11
  94. package/search/types.ts +102 -103
  95. package/service/index.ts +11 -11
  96. package/service/protocol/index.ts +217 -14
  97. package/types/division-box.ts +248 -0
  98. package/types/download.ts +72 -34
  99. package/types/icon.ts +2 -1
  100. package/types/index.ts +3 -1
  101. package/types/intelligence.ts +413 -0
  102. package/types/modules/base.ts +16 -16
  103. package/types/modules/index.ts +1 -1
  104. package/types/modules/module-lifecycle.ts +21 -21
  105. package/types/modules/module-manager.ts +11 -11
  106. package/types/modules/module.ts +16 -16
  107. package/types/storage.ts +0 -1
  108. package/types/touch-app-core.ts +32 -32
  109. package/types/update.ts +79 -21
  110. package/core-box/README.md +0 -218
  111. package/core-box/builder/tuff-builder.example.ts.bak +0 -258
  112. package/core-box/run-tests.sh +0 -7
  113. package/core-box/search.ts +0 -1
package/plugin/preload.ts CHANGED
@@ -1,18 +1,21 @@
1
1
  import type { ITouchClientChannel } from '../channel'
2
+ import type { ITouchSDK } from './sdk/index'
3
+ // Import SDK for side effects (initializes hooks)
2
4
  import './sdk/index'
3
5
 
4
- // window type
6
+ // window type - includes both plugin preload types and SDK types
5
7
  declare global {
6
- export interface Window {
8
+ interface Window {
7
9
  $plugin: {
8
10
  name: string
9
- path: Object
11
+ path: object
10
12
  }
11
13
  $channel: ITouchClientChannel
12
14
  $crash: (message: string, extraData: any) => void
13
15
  $config: {
14
16
  themeStyle: any
15
17
  }
18
+ $touchSDK: ITouchSDK
16
19
  }
17
20
  }
18
21
 
@@ -1,18 +1,18 @@
1
- import { defaultRiskPromptHandler } from '../risk'
2
1
  import type { PluginInstallRequest, PluginInstallResult, PluginProvider, PluginProviderContext } from './types'
2
+ import { defaultRiskPromptHandler } from '../risk'
3
3
 
4
4
  class ProviderRegistry {
5
5
  private providers: PluginProvider[] = []
6
6
 
7
7
  register(provider: PluginProvider): void {
8
- if (this.providers.some((item) => item.type === provider.type)) {
8
+ if (this.providers.some(item => item.type === provider.type)) {
9
9
  throw new Error(`Plugin provider '${provider.type}' already registered`)
10
10
  }
11
11
  this.providers.push(provider)
12
12
  }
13
13
 
14
14
  unregister(type: PluginProvider['type']): void {
15
- this.providers = this.providers.filter((item) => item.type !== type)
15
+ this.providers = this.providers.filter(item => item.type !== type)
16
16
  }
17
17
 
18
18
  clear(): void {
@@ -20,19 +20,20 @@ class ProviderRegistry {
20
20
  }
21
21
 
22
22
  resolve(request: PluginInstallRequest): PluginProvider | undefined {
23
- return this.providers.find((provider) => provider.canHandle(request))
23
+ return this.providers.find(provider => provider.canHandle(request))
24
24
  }
25
25
 
26
26
  async install(
27
27
  request: PluginInstallRequest,
28
- context: PluginProviderContext = {}
28
+ context: PluginProviderContext = {},
29
29
  ): Promise<PluginInstallResult | undefined> {
30
30
  const provider = this.resolve(request)
31
- if (!provider) return undefined
31
+ if (!provider)
32
+ return undefined
32
33
 
33
34
  const composedContext: PluginProviderContext = {
34
35
  riskPrompt: defaultRiskPromptHandler,
35
- ...context
36
+ ...context,
36
37
  }
37
38
 
38
39
  if (!composedContext.riskPrompt) {
@@ -1,5 +1,5 @@
1
- import type { IDownloadOptions, IDownloadResult } from '../plugin-source'
2
1
  import type { IManifest } from '..'
2
+ import type { IDownloadOptions, IDownloadResult } from '../plugin-source'
3
3
  import type { RiskPromptHandler } from '../risk'
4
4
 
5
5
  export enum PluginProviderType {
@@ -7,7 +7,7 @@ export enum PluginProviderType {
7
7
  NPM = 'npm',
8
8
  TPEX = 'tpex',
9
9
  FILE = 'file',
10
- DEV = 'dev'
10
+ DEV = 'dev',
11
11
  }
12
12
 
13
13
  export interface PluginInstallRequest {
@@ -43,11 +43,11 @@ export interface PluginInstallResult extends IDownloadResult {
43
43
 
44
44
  export interface PluginProvider {
45
45
  readonly type: PluginProviderType
46
- canHandle(request: PluginInstallRequest): boolean
47
- install(
46
+ canHandle: (request: PluginInstallRequest) => boolean
47
+ install: (
48
48
  request: PluginInstallRequest,
49
- context?: PluginProviderContext
50
- ): Promise<PluginInstallResult>
49
+ context?: PluginProviderContext,
50
+ ) => Promise<PluginInstallResult>
51
51
  }
52
52
 
53
53
  export interface PluginInstallSummary {
@@ -1,48 +1,48 @@
1
- import type { ITouchClientChannel } from '@talex-touch/utils/channel';
2
- import { genChannel } from '../channel';
3
- import type { IPluginRendererChannel, PluginChannelHandler } from './types';
1
+ import type { ITouchClientChannel } from '@talex-touch/utils/channel'
2
+ import type { IPluginRendererChannel, PluginChannelHandler } from './types'
3
+ import { genChannel } from '../channel'
4
4
 
5
- const ensureClientChannel = (): ITouchClientChannel => genChannel();
5
+ const ensureClientChannel = (): ITouchClientChannel => genChannel()
6
6
 
7
7
  export function createPluginRendererChannel(): IPluginRendererChannel {
8
- const client = ensureClientChannel();
8
+ const client = ensureClientChannel()
9
9
 
10
10
  return {
11
11
  send(eventName, payload) {
12
- return client.send(eventName, payload);
12
+ return client.send(eventName, payload)
13
13
  },
14
14
 
15
15
  sendSync(eventName, payload) {
16
- return client.sendSync(eventName, payload);
16
+ return client.sendSync(eventName, payload)
17
17
  },
18
18
 
19
19
  on(eventName, handler) {
20
- return client.regChannel(eventName, handler);
20
+ return client.regChannel(eventName, handler)
21
21
  },
22
22
 
23
23
  once(eventName, handler) {
24
- let dispose: () => void = () => void 0;
24
+ let dispose: () => void = () => void 0
25
25
  const wrapped: PluginChannelHandler = (event) => {
26
- dispose();
27
- handler(event);
28
- };
26
+ dispose()
27
+ handler(event)
28
+ }
29
29
 
30
- dispose = client.regChannel(eventName, wrapped);
31
- return dispose;
30
+ dispose = client.regChannel(eventName, wrapped)
31
+ return dispose
32
32
  },
33
33
 
34
34
  get raw() {
35
- return client;
36
- }
37
- };
35
+ return client
36
+ },
37
+ }
38
38
  }
39
39
 
40
- let cachedRendererChannel: IPluginRendererChannel | null = null;
40
+ let cachedRendererChannel: IPluginRendererChannel | null = null
41
41
 
42
42
  export function usePluginRendererChannel(): IPluginRendererChannel {
43
43
  if (!cachedRendererChannel) {
44
- cachedRendererChannel = createPluginRendererChannel();
44
+ cachedRendererChannel = createPluginRendererChannel()
45
45
  }
46
46
 
47
- return cachedRendererChannel;
47
+ return cachedRendererChannel
48
48
  }
@@ -1,6 +1,6 @@
1
1
  import type { PluginClipboardHistoryResponse, PluginClipboardItem } from './types'
2
2
 
3
- const ensurePluginChannel = () => {
3
+ function ensurePluginChannel() {
4
4
  const channel = (window as any)?.$channel
5
5
  if (!channel) {
6
6
  throw new Error('[Plugin SDK] Clipboard channel requires plugin renderer context with $channel available.')
@@ -8,13 +8,15 @@ const ensurePluginChannel = () => {
8
8
  return channel
9
9
  }
10
10
 
11
- const normalizeItem = (item: PluginClipboardItem | null): PluginClipboardItem | null => {
12
- if (!item) return item
11
+ function normalizeItem(item: PluginClipboardItem | null): PluginClipboardItem | null {
12
+ if (!item)
13
+ return item
13
14
  if (!item.meta && typeof item.metadata === 'string') {
14
15
  try {
15
16
  const parsed = JSON.parse(item.metadata)
16
17
  return { ...item, meta: parsed }
17
- } catch {
18
+ }
19
+ catch {
18
20
  return { ...item, meta: null }
19
21
  }
20
22
  }
@@ -61,7 +63,7 @@ export function useClipboardHistory() {
61
63
  : []
62
64
  return {
63
65
  ...response,
64
- history
66
+ history,
65
67
  }
66
68
  },
67
69
 
@@ -94,6 +96,6 @@ export function useClipboardHistory() {
94
96
  return Boolean((response as any).success)
95
97
  }
96
98
  return true
97
- }
99
+ },
98
100
  }
99
101
  }
@@ -17,8 +17,10 @@ export function regShortcut(key: string, func: Function): boolean {
17
17
  const channel = genChannel()
18
18
 
19
19
  const res = channel.sendSync('shortcon:reg', { key })
20
- if (res instanceof String) throw new Error(String(res))
21
- if (res === false) return false
20
+ if (res instanceof String)
21
+ throw new Error(String(res))
22
+ if (res === false)
23
+ return false
22
24
 
23
25
  channel.regChannel('shortcon:trigger', ({ data }) => key === data.key && func())
24
26
 
@@ -33,16 +35,17 @@ export function regShortcut(key: string, func: Function): boolean {
33
35
  */
34
36
  export async function communicateWithPlugin(
35
37
  key: string,
36
- info: any = {}
38
+ info: any = {},
37
39
  ): Promise<any> {
38
40
  const channel = genChannel()
39
41
 
40
42
  try {
41
43
  return await channel.send('index:communicate', {
42
44
  key,
43
- info
45
+ info,
44
46
  })
45
- } catch (error) {
47
+ }
48
+ catch (error) {
46
49
  console.error(`[Plugin SDK] Failed to communicate`, error)
47
50
  throw error
48
51
  }
@@ -59,7 +62,8 @@ export async function sendMessage(message: string, data: any = {}): Promise<any>
59
62
 
60
63
  try {
61
64
  return await channel.send(`plugin:${message}`, data)
62
- } catch (error) {
65
+ }
66
+ catch (error) {
63
67
  console.error(`[Plugin SDK] Failed to send message: ${message}`, error)
64
68
  throw error
65
69
  }
@@ -1,6 +1,6 @@
1
1
  import type { IPluginRendererChannel } from './types'
2
2
 
3
- const ensurePluginContext = (): { channel: IPluginRendererChannel; pluginName: string } => {
3
+ function ensurePluginContext(): { channel: IPluginRendererChannel, pluginName: string } {
4
4
  const plugin = (window as any)?.$plugin
5
5
  if (!plugin?.name) {
6
6
  throw new Error('[TouchSDK] Unable to resolve plugin name inside renderer context.')
@@ -13,7 +13,7 @@ const ensurePluginContext = (): { channel: IPluginRendererChannel; pluginName: s
13
13
 
14
14
  return {
15
15
  channel,
16
- pluginName: plugin.name as string
16
+ pluginName: plugin.name as string,
17
17
  }
18
18
  }
19
19
 
@@ -24,4 +24,3 @@ export async function clearCoreBoxItems(): Promise<void> {
24
24
  const { channel, pluginName } = ensurePluginContext()
25
25
  await channel.send('core-box:clear-items', { pluginName })
26
26
  }
27
-
@@ -0,0 +1,266 @@
1
+ /**
2
+ * DivisionBox SDK for Plugin Development
3
+ *
4
+ * Provides a simple API for plugins to create and manage DivisionBox instances.
5
+ * DivisionBox is a lightweight floating window container for plugin UIs and tools.
6
+ */
7
+
8
+ import type {
9
+ CloseOptions,
10
+ DivisionBoxConfig,
11
+ DivisionBoxState,
12
+ SessionInfo,
13
+ } from '../../types/division-box'
14
+
15
+ /**
16
+ * State change event handler
17
+ */
18
+ export type StateChangeHandler = (data: {
19
+ sessionId: string
20
+ state: DivisionBoxState
21
+ }) => void
22
+
23
+ /**
24
+ * DivisionBox SDK interface for plugins
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Open a DivisionBox
29
+ * const { sessionId } = await plugin.divisionBox.open({
30
+ * url: 'https://example.com/tool',
31
+ * title: 'My Tool',
32
+ * size: 'medium',
33
+ * keepAlive: true
34
+ * })
35
+ *
36
+ * // Listen for state changes
37
+ * plugin.divisionBox.onStateChange((data) => {
38
+ * console.log(`Session ${data.sessionId} is now ${data.state}`)
39
+ * })
40
+ *
41
+ * // Close the DivisionBox
42
+ * await plugin.divisionBox.close(sessionId)
43
+ * ```
44
+ */
45
+ export interface DivisionBoxSDK {
46
+ /**
47
+ * Opens a new DivisionBox instance
48
+ *
49
+ * @param config - Configuration for the DivisionBox
50
+ * @returns Promise resolving to session information
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const { sessionId } = await plugin.divisionBox.open({
55
+ * url: 'https://example.com',
56
+ * title: 'Web Tool',
57
+ * icon: 'ri:tools-line',
58
+ * size: 'medium',
59
+ * keepAlive: true,
60
+ * header: {
61
+ * show: true,
62
+ * title: 'Custom Title',
63
+ * actions: [
64
+ * { label: 'Refresh', icon: 'ri:refresh-line', onClick: () => {} }
65
+ * ]
66
+ * }
67
+ * })
68
+ * ```
69
+ */
70
+ open(config: DivisionBoxConfig): Promise<SessionInfo>
71
+
72
+ /**
73
+ * Closes a DivisionBox instance
74
+ *
75
+ * @param sessionId - The session ID to close
76
+ * @param options - Optional close options
77
+ * @returns Promise that resolves when closed
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // Simple close
82
+ * await plugin.divisionBox.close(sessionId)
83
+ *
84
+ * // Close with delay and animation
85
+ * await plugin.divisionBox.close(sessionId, {
86
+ * delay: 1000,
87
+ * animation: true
88
+ * })
89
+ *
90
+ * // Force close (ignore keepAlive)
91
+ * await plugin.divisionBox.close(sessionId, {
92
+ * force: true
93
+ * })
94
+ * ```
95
+ */
96
+ close(sessionId: string, options?: CloseOptions): Promise<void>
97
+
98
+ /**
99
+ * Registers a state change listener
100
+ *
101
+ * @param handler - Callback function for state changes
102
+ * @returns Unsubscribe function
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const unsubscribe = plugin.divisionBox.onStateChange((data) => {
107
+ * console.log(`Session ${data.sessionId} changed to ${data.state}`)
108
+ * })
109
+ *
110
+ * // Later, unsubscribe
111
+ * unsubscribe()
112
+ * ```
113
+ */
114
+ onStateChange(handler: StateChangeHandler): () => void
115
+
116
+ /**
117
+ * Updates session state data
118
+ *
119
+ * @param sessionId - The session ID
120
+ * @param key - State key
121
+ * @param value - State value
122
+ * @returns Promise that resolves when updated
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * // Save scroll position
127
+ * await plugin.divisionBox.updateState(sessionId, 'scrollY', 150)
128
+ *
129
+ * // Save draft content
130
+ * await plugin.divisionBox.updateState(sessionId, 'draft', {
131
+ * text: 'Hello world',
132
+ * timestamp: Date.now()
133
+ * })
134
+ * ```
135
+ */
136
+ updateState(sessionId: string, key: string, value: any): Promise<void>
137
+
138
+ /**
139
+ * Gets session state data
140
+ *
141
+ * @param sessionId - The session ID
142
+ * @param key - State key
143
+ * @returns Promise resolving to the state value
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const scrollY = await plugin.divisionBox.getState(sessionId, 'scrollY')
148
+ * const draft = await plugin.divisionBox.getState(sessionId, 'draft')
149
+ * ```
150
+ */
151
+ getState(sessionId: string, key: string): Promise<any>
152
+ }
153
+
154
+ /**
155
+ * Creates a DivisionBox SDK instance for plugin use
156
+ *
157
+ * @param channel - The plugin channel bridge for IPC communication
158
+ * @returns Configured DivisionBox SDK instance
159
+ *
160
+ * @internal
161
+ */
162
+ export function createDivisionBoxSDK(channel: any): DivisionBoxSDK {
163
+ const stateChangeHandlers: Set<StateChangeHandler> = new Set()
164
+
165
+ // Register listener for state change events from main process
166
+ // The channel can be either IPluginChannelBridge (main process) or window.$channel (renderer)
167
+ const registerListener = () => {
168
+ if (channel.onMain) {
169
+ // Main process plugin context
170
+ channel.onMain('division-box:state-changed', (event: any) => {
171
+ stateChangeHandlers.forEach(handler => handler(event.data || event))
172
+ })
173
+ } else if (channel.on) {
174
+ // Renderer process context
175
+ channel.on('division-box:state-changed', (data: any) => {
176
+ stateChangeHandlers.forEach(handler => handler(data))
177
+ })
178
+ }
179
+ }
180
+
181
+ registerListener()
182
+
183
+ return {
184
+ async open(config: DivisionBoxConfig): Promise<SessionInfo> {
185
+ // Send to main process
186
+ const sendFn = channel.sendToMain || channel.send
187
+ const result = await sendFn('division-box:open', config)
188
+
189
+ if (!result.success) {
190
+ throw new Error(result.error?.message || 'Failed to open DivisionBox')
191
+ }
192
+
193
+ return result.data
194
+ },
195
+
196
+ async close(sessionId: string, options?: CloseOptions): Promise<void> {
197
+ const sendFn = channel.sendToMain || channel.send
198
+ const result = await sendFn('division-box:close', { sessionId, options })
199
+
200
+ if (!result.success) {
201
+ throw new Error(result.error?.message || 'Failed to close DivisionBox')
202
+ }
203
+ },
204
+
205
+ onStateChange(handler: StateChangeHandler): () => void {
206
+ stateChangeHandlers.add(handler)
207
+
208
+ return () => {
209
+ stateChangeHandlers.delete(handler)
210
+ }
211
+ },
212
+
213
+ async updateState(sessionId: string, key: string, value: any): Promise<void> {
214
+ const sendFn = channel.sendToMain || channel.send
215
+ const result = await sendFn('division-box:update-state', {
216
+ sessionId,
217
+ key,
218
+ value
219
+ })
220
+
221
+ if (!result.success) {
222
+ throw new Error(result.error?.message || 'Failed to update state')
223
+ }
224
+ },
225
+
226
+ async getState(sessionId: string, key: string): Promise<any> {
227
+ const sendFn = channel.sendToMain || channel.send
228
+ const result = await sendFn('division-box:get-state', {
229
+ sessionId,
230
+ key
231
+ })
232
+
233
+ if (!result.success) {
234
+ throw new Error(result.error?.message || 'Failed to get state')
235
+ }
236
+
237
+ return result.data
238
+ }
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Hook for using DivisionBox SDK in plugin context
244
+ *
245
+ * @returns DivisionBox SDK instance
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * const divisionBox = useDivisionBox()
250
+ *
251
+ * const { sessionId } = await divisionBox.open({
252
+ * url: 'https://example.com',
253
+ * title: 'My Tool'
254
+ * })
255
+ * ```
256
+ */
257
+ export function useDivisionBox(): DivisionBoxSDK {
258
+ // @ts-ignore - window.$channel is injected by the plugin system
259
+ const channel = window.$channel
260
+
261
+ if (!channel) {
262
+ throw new Error('[DivisionBox SDK] Channel not available. Make sure this is called in a plugin context.')
263
+ }
264
+
265
+ return createDivisionBoxSDK(channel)
266
+ }
@@ -1,4 +1,4 @@
1
1
  export enum BridgeEventForCoreBox {
2
2
  CORE_BOX_INPUT_CHANGE = 'core-box:input-change',
3
- CORE_BOX_CLIPBOARD_CHANGE = 'core-box:clipboard-change'
3
+ CORE_BOX_CLIPBOARD_CHANGE = 'core-box:clipboard-change',
4
4
  }
@@ -185,7 +185,7 @@ window.storageOnDidChangeExample = {
185
185
  setupMultipleFileListeners,
186
186
  setupDynamicListener,
187
187
  setupConditionalListener,
188
- setupBatchOperationListener
188
+ setupBatchOperationListener,
189
189
  }
190
190
 
191
191
  // 自动运行示例(可选)