@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.
- package/animation/window-node.ts +205 -0
- package/animation/window.ts +19 -15
- package/auth/clerk-types.ts +1 -1
- package/auth/index.ts +1 -1
- package/auth/useAuthState.ts +6 -5
- package/auth/useClerkConfig.ts +6 -6
- package/auth/useClerkProvider.ts +3 -2
- package/channel/index.ts +28 -21
- package/common/file-scan-constants.ts +137 -121
- package/common/file-scan-utils.ts +49 -25
- package/common/index.ts +3 -3
- package/common/search/gather.ts +1 -1
- package/common/search/index.ts +5 -6
- package/common/storage/constants.ts +3 -2
- package/common/storage/entity/app-settings.ts +19 -3
- package/common/storage/entity/shortcut-settings.ts +10 -10
- package/common/storage/shortcut-storage.ts +6 -4
- package/common/utils/file.ts +15 -4
- package/common/utils/index.ts +62 -52
- package/common/utils/polling.ts +114 -63
- package/common/utils/task-queue.ts +11 -10
- package/common/utils/time.ts +50 -47
- package/common/utils/timing.ts +41 -37
- package/core-box/builder/index.ts +1 -1
- package/core-box/builder/tuff-builder.ts +255 -230
- package/core-box/index.ts +3 -6
- package/core-box/preview/index.ts +1 -0
- package/core-box/preview/types.ts +43 -0
- package/core-box/tuff/index.ts +1 -1
- package/core-box/tuff/tuff-dsl.ts +419 -253
- package/electron/clipboard-helper.ts +20 -12
- package/electron/download-manager.ts +43 -42
- package/electron/env-tool.ts +19 -18
- package/electron/file-parsers/index.ts +2 -2
- package/electron/file-parsers/parsers/text-parser.ts +15 -14
- package/electron/file-parsers/registry.ts +9 -7
- package/electron/file-parsers/types.ts +4 -4
- package/electron/index.ts +1 -1
- package/eventbus/index.ts +11 -11
- package/index.ts +6 -5
- package/intelligence/client.ts +87 -0
- package/intelligence/index.ts +1 -0
- package/package.json +14 -14
- package/permission/index.ts +8 -8
- package/plugin/channel.ts +77 -68
- package/plugin/index.ts +113 -84
- package/plugin/install.ts +8 -8
- package/plugin/log/types.ts +5 -5
- package/plugin/node/index.ts +1 -1
- package/plugin/node/logger-manager.ts +14 -11
- package/plugin/node/logger.ts +8 -8
- package/plugin/plugin-source.ts +11 -11
- package/plugin/preload.ts +6 -3
- package/plugin/providers/registry.ts +8 -7
- package/plugin/providers/types.ts +6 -6
- package/plugin/sdk/channel.ts +20 -20
- package/plugin/sdk/clipboard.ts +8 -6
- package/plugin/sdk/common.ts +10 -6
- package/plugin/sdk/core-box.ts +2 -3
- package/plugin/sdk/division-box.ts +266 -0
- package/plugin/sdk/enum/bridge-event.ts +1 -1
- package/plugin/sdk/examples/storage-onDidChange-example.js +1 -1
- package/plugin/sdk/features.ts +34 -26
- package/plugin/sdk/hooks/bridge.ts +3 -6
- package/plugin/sdk/hooks/index.ts +1 -1
- package/plugin/sdk/hooks/life-cycle.ts +4 -10
- package/plugin/sdk/index.ts +9 -13
- package/plugin/sdk/service/index.ts +3 -3
- package/plugin/sdk/storage.ts +4 -4
- package/plugin/sdk/system.ts +1 -1
- package/plugin/sdk/types.ts +169 -143
- package/plugin/sdk/window/index.ts +8 -5
- package/preload/loading.ts +6 -6
- package/preload/renderer.ts +4 -2
- package/renderer/hooks/arg-mapper.ts +1 -2
- package/renderer/hooks/index.ts +2 -0
- package/renderer/hooks/initialize.ts +10 -8
- package/renderer/hooks/performance.ts +4 -4
- package/renderer/hooks/use-channel.ts +150 -0
- package/renderer/hooks/use-intelligence.ts +236 -0
- package/renderer/index.ts +6 -1
- package/renderer/ref.ts +32 -36
- package/renderer/slots.ts +29 -26
- package/renderer/storage/app-settings.ts +16 -6
- package/renderer/storage/base-storage.ts +236 -88
- package/renderer/storage/index.ts +3 -0
- package/renderer/storage/intelligence-storage.ts +215 -0
- package/renderer/storage/openers.ts +13 -3
- package/renderer/touch-sdk/env.ts +41 -41
- package/renderer/touch-sdk/index.ts +1 -1
- package/renderer/touch-sdk/terminal.ts +5 -5
- package/renderer/touch-sdk/utils.ts +4 -3
- package/search/levenshtein-utils.ts +11 -11
- package/search/types.ts +102 -103
- package/service/index.ts +11 -11
- package/service/protocol/index.ts +217 -14
- package/types/division-box.ts +248 -0
- package/types/download.ts +72 -34
- package/types/icon.ts +2 -1
- package/types/index.ts +3 -1
- package/types/intelligence.ts +413 -0
- package/types/modules/base.ts +16 -16
- package/types/modules/index.ts +1 -1
- package/types/modules/module-lifecycle.ts +21 -21
- package/types/modules/module-manager.ts +11 -11
- package/types/modules/module.ts +16 -16
- package/types/storage.ts +0 -1
- package/types/touch-app-core.ts +32 -32
- package/types/update.ts +79 -21
- package/core-box/README.md +0 -218
- package/core-box/builder/tuff-builder.example.ts.bak +0 -258
- package/core-box/run-tests.sh +0 -7
- package/core-box/search.ts +0 -1
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { genChannel } from '../../channel';
|
|
2
1
|
import type {
|
|
3
|
-
BrowserWindowConstructorOptions,
|
|
4
2
|
BrowserWindow,
|
|
3
|
+
BrowserWindowConstructorOptions,
|
|
5
4
|
WebContents,
|
|
6
5
|
} from 'electron'
|
|
6
|
+
import { genChannel } from '../../channel'
|
|
7
7
|
|
|
8
8
|
export function createWindow(options: BrowserWindowConstructorOptions & { file?: string } & { url?: string }): number {
|
|
9
9
|
const res = genChannel().sendSync('window:new', options)
|
|
10
|
-
if (res.error)
|
|
10
|
+
if (res.error)
|
|
11
|
+
throw new Error(res.error)
|
|
11
12
|
|
|
12
13
|
return res.id
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export function toggleWinVisible(id: number, visible?: boolean): boolean {
|
|
16
17
|
const res = genChannel().sendSync('window:visible', visible !== undefined ? { id, visible } : { id })
|
|
17
|
-
if (res.error)
|
|
18
|
+
if (res.error)
|
|
19
|
+
throw new Error(res.error)
|
|
18
20
|
|
|
19
21
|
return res.visible
|
|
20
22
|
}
|
|
@@ -23,7 +25,8 @@ export function setWindowProperty(id: number, property: {
|
|
|
23
25
|
|
|
24
26
|
}): boolean {
|
|
25
27
|
const res = genChannel().sendSync('window:property', { id, property })
|
|
26
|
-
if (res.error)
|
|
28
|
+
if (res.error)
|
|
29
|
+
throw new Error(res.error)
|
|
27
30
|
|
|
28
31
|
return res.success
|
|
29
32
|
}
|
package/preload/loading.ts
CHANGED
|
@@ -4,12 +4,12 @@ export type LoadingMode = 'classic' | 'progress' | 'debug'
|
|
|
4
4
|
|
|
5
5
|
export type LoadingState = 'start' | 'finish'
|
|
6
6
|
|
|
7
|
-
export type LoadingEvent
|
|
8
|
-
| { type: 'mode'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
export type LoadingEvent
|
|
8
|
+
= | { type: 'mode', mode: LoadingMode }
|
|
9
|
+
| { type: 'message', message: string }
|
|
10
|
+
| { type: 'progress', delta?: number, reset?: boolean }
|
|
11
|
+
| { type: 'state', state: LoadingState }
|
|
12
12
|
|
|
13
13
|
export interface PreloadAPI {
|
|
14
|
-
sendPreloadEvent(event: LoadingEvent)
|
|
14
|
+
sendPreloadEvent: (event: LoadingEvent) => void
|
|
15
15
|
}
|
package/preload/renderer.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { LoadingEvent, LoadingMode, LoadingState, PreloadAPI } from './loading'
|
|
2
2
|
|
|
3
3
|
function getPreloadApi(): PreloadAPI | null {
|
|
4
|
-
if (typeof window === 'undefined')
|
|
4
|
+
if (typeof window === 'undefined')
|
|
5
|
+
return null
|
|
5
6
|
return (window as any).api ?? null
|
|
6
7
|
}
|
|
7
8
|
|
|
@@ -36,6 +37,7 @@ export function preloadDebugStep(message: string, delta = 0.08): void {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
export function preloadRemoveOverlay(): void {
|
|
39
|
-
if (typeof window === 'undefined')
|
|
40
|
+
if (typeof window === 'undefined')
|
|
41
|
+
return
|
|
40
42
|
window.postMessage({ payload: 'removeLoading' }, '*')
|
|
41
43
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
2
|
* Interface for command line argument mapper options
|
|
4
3
|
* @interface IArgMapperOptions
|
|
@@ -33,7 +32,7 @@ declare global {
|
|
|
33
32
|
* @returns Mapped command line arguments as key-value pairs
|
|
34
33
|
*/
|
|
35
34
|
export function useArgMapper(args: string[] = process.argv): IArgMapperOptions {
|
|
36
|
-
if (
|
|
35
|
+
if (window.$argMapper) {
|
|
37
36
|
return window.$argMapper
|
|
38
37
|
}
|
|
39
38
|
|
package/renderer/hooks/index.ts
CHANGED
|
@@ -56,7 +56,8 @@ function checkWebGLSupport(): boolean {
|
|
|
56
56
|
try {
|
|
57
57
|
const canvas = document.createElement('canvas')
|
|
58
58
|
return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
|
|
59
|
-
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
60
61
|
return false
|
|
61
62
|
}
|
|
62
63
|
}
|
|
@@ -69,7 +70,8 @@ function checkWebGL2Support(): boolean {
|
|
|
69
70
|
try {
|
|
70
71
|
const canvas = document.createElement('canvas')
|
|
71
72
|
return !!canvas.getContext('webgl2')
|
|
72
|
-
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
73
75
|
return false
|
|
74
76
|
}
|
|
75
77
|
}
|
|
@@ -109,25 +111,25 @@ export function useInitialize(): IInitializationInfo {
|
|
|
109
111
|
screenResolution: {
|
|
110
112
|
width: screen.width,
|
|
111
113
|
height: screen.height,
|
|
112
|
-
pixelRatio: window.devicePixelRatio || 1
|
|
114
|
+
pixelRatio: window.devicePixelRatio || 1,
|
|
113
115
|
},
|
|
114
116
|
windowSize: {
|
|
115
117
|
innerWidth: window.innerWidth,
|
|
116
118
|
innerHeight: window.innerHeight,
|
|
117
119
|
outerWidth: window.outerWidth,
|
|
118
|
-
outerHeight: window.outerHeight
|
|
120
|
+
outerHeight: window.outerHeight,
|
|
119
121
|
},
|
|
120
122
|
performance: {
|
|
121
123
|
navigationStart: performance.timeOrigin || now,
|
|
122
124
|
loadEventEnd: (performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming)?.loadEventEnd || undefined,
|
|
123
|
-
domContentLoadedEventEnd: (performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming)?.domContentLoadedEventEnd || undefined
|
|
125
|
+
domContentLoadedEventEnd: (performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming)?.domContentLoadedEventEnd || undefined,
|
|
124
126
|
},
|
|
125
127
|
capabilities: {
|
|
126
128
|
webgl: checkWebGLSupport(),
|
|
127
129
|
webgl2: checkWebGL2Support(),
|
|
128
130
|
webAudio: checkWebAudioSupport(),
|
|
129
|
-
serviceWorker: checkServiceWorkerSupport()
|
|
130
|
-
}
|
|
131
|
+
serviceWorker: checkServiceWorkerSupport(),
|
|
132
|
+
},
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
return window.$initInfo = initInfo
|
|
@@ -191,7 +193,7 @@ export function refreshPerformanceInfo(): IInitializationInfo {
|
|
|
191
193
|
window.$initInfo.performance = {
|
|
192
194
|
navigationStart: performance.timeOrigin || window.$initInfo.performance.navigationStart,
|
|
193
195
|
loadEventEnd: navigationEntry?.loadEventEnd || undefined,
|
|
194
|
-
domContentLoadedEventEnd: navigationEntry?.domContentLoadedEventEnd || undefined
|
|
196
|
+
domContentLoadedEventEnd: navigationEntry?.domContentLoadedEventEnd || undefined,
|
|
195
197
|
}
|
|
196
198
|
}
|
|
197
199
|
return window.$initInfo
|
|
@@ -41,7 +41,7 @@ export function getRendererPerformanceMetrics(): RendererPerformanceMetrics {
|
|
|
41
41
|
loadEventEnd: navEntry?.loadEventEnd,
|
|
42
42
|
domInteractive: navEntry?.domInteractive,
|
|
43
43
|
firstPaint: firstPaint?.startTime,
|
|
44
|
-
firstContentfulPaint: firstContentfulPaint?.startTime
|
|
44
|
+
firstContentfulPaint: firstContentfulPaint?.startTime,
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -55,7 +55,8 @@ export function collectPerformanceMetricsOnLoad(): Promise<RendererPerformanceMe
|
|
|
55
55
|
setTimeout(() => {
|
|
56
56
|
resolve(getRendererPerformanceMetrics())
|
|
57
57
|
}, 0)
|
|
58
|
-
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
59
60
|
// Wait for load event
|
|
60
61
|
window.addEventListener('load', () => {
|
|
61
62
|
setTimeout(() => {
|
|
@@ -81,7 +82,6 @@ export function getPerformanceSummary(): {
|
|
|
81
82
|
domReady: metrics.domContentLoadedEventEnd || 0,
|
|
82
83
|
pageLoad: metrics.loadEventEnd || 0,
|
|
83
84
|
firstPaint: metrics.firstPaint,
|
|
84
|
-
firstContentfulPaint: metrics.firstContentfulPaint
|
|
85
|
+
firstContentfulPaint: metrics.firstContentfulPaint,
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
|
-
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { InjectionKey } from 'vue'
|
|
2
|
+
import { inject } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface TouchChannel {
|
|
5
|
+
send: <TRequest = any, TResponse = any>(
|
|
6
|
+
eventName: string,
|
|
7
|
+
data?: TRequest,
|
|
8
|
+
) => Promise<TResponse>
|
|
9
|
+
|
|
10
|
+
regChannel?: <TRequest = any>(
|
|
11
|
+
eventName: string,
|
|
12
|
+
handler: (data: TRequest) => Promise<any> | any,
|
|
13
|
+
) => () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Injection key for the TouchChannel
|
|
17
|
+
export const TouchChannelKey: InjectionKey<TouchChannel> = Symbol('TouchChannel')
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Global reference to the TouchChannel instance
|
|
21
|
+
* This is automatically injected by the main process
|
|
22
|
+
*/
|
|
23
|
+
declare global {
|
|
24
|
+
interface Window {
|
|
25
|
+
touchChannel?: TouchChannel
|
|
26
|
+
$touchChannel?: TouchChannel
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var touchChannel: TouchChannel | undefined
|
|
30
|
+
var $touchChannel: TouchChannel | undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resolve TouchChannel from multiple sources
|
|
35
|
+
*/
|
|
36
|
+
function resolveTouchChannel(): TouchChannel | null {
|
|
37
|
+
// Try dependency injection first
|
|
38
|
+
try {
|
|
39
|
+
const injectedChannel = inject(TouchChannelKey, null)
|
|
40
|
+
if (injectedChannel)
|
|
41
|
+
return injectedChannel
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Ignore injection errors outside of Vue context
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Try global variables
|
|
48
|
+
if (typeof globalThis !== 'undefined') {
|
|
49
|
+
const channel
|
|
50
|
+
= (globalThis as any).touchChannel
|
|
51
|
+
|| (globalThis as any).$touchChannel
|
|
52
|
+
|| (globalThis as any).window?.touchChannel
|
|
53
|
+
|| (globalThis as any).window?.$touchChannel
|
|
54
|
+
|
|
55
|
+
if (channel)
|
|
56
|
+
return channel
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Try window object (browser environment)
|
|
60
|
+
if (typeof window !== 'undefined') {
|
|
61
|
+
const channel = window.touchChannel || window.$touchChannel
|
|
62
|
+
if (channel)
|
|
63
|
+
return channel
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Composable for using TouchChannel communication
|
|
71
|
+
*
|
|
72
|
+
* Provides a reactive interface to communicate with the main process
|
|
73
|
+
* through the TouchChannel IPC system. Works in both renderer and
|
|
74
|
+
* corebox contexts.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const channel = useChannel()
|
|
79
|
+
*
|
|
80
|
+
* // Send a message to main process
|
|
81
|
+
* const result = await channel.send('get-app-config')
|
|
82
|
+
*
|
|
83
|
+
* // Send with data
|
|
84
|
+
* const saved = await channel.send('save-config', { theme: 'dark' })
|
|
85
|
+
*
|
|
86
|
+
* // Register a handler (if supported)
|
|
87
|
+
* const cleanup = channel.regChannel?.('config-updated', (data) => {
|
|
88
|
+
* console.log('Config updated:', data)
|
|
89
|
+
* })
|
|
90
|
+
*
|
|
91
|
+
* // Cleanup handler when component unmounts
|
|
92
|
+
* onUnmounted(() => {
|
|
93
|
+
* cleanup?.()
|
|
94
|
+
* })
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function useChannel(): TouchChannel {
|
|
98
|
+
const channel = resolveTouchChannel()
|
|
99
|
+
|
|
100
|
+
if (!channel) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
'[useChannel] TouchChannel not available. '
|
|
103
|
+
+ 'Make sure the TouchChannel is properly injected by the main process.',
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return channel
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Helper composable that creates a typed channel wrapper
|
|
112
|
+
* for specific communication patterns
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* interface ConfigAPI {
|
|
117
|
+
* 'get-config': { key: string } => { value: any }
|
|
118
|
+
* 'set-config': { key: string; value: any } => { success: boolean }
|
|
119
|
+
* }
|
|
120
|
+
*
|
|
121
|
+
* const configChannel = useTypedChannel<ConfigAPI>()
|
|
122
|
+
*
|
|
123
|
+
* // Type-safe usage
|
|
124
|
+
* const result = await configChannel.send('get-config', { key: 'theme' })
|
|
125
|
+
* // result is automatically typed as { value: any }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export function useTypedChannel<TChannelMap extends Record<string, any>>() {
|
|
129
|
+
const channel = useChannel()
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
send<TEventName extends keyof TChannelMap>(
|
|
133
|
+
eventName: TEventName,
|
|
134
|
+
...args: TChannelMap[TEventName] extends (arg: infer TArg) => any
|
|
135
|
+
? [TArg]
|
|
136
|
+
: []
|
|
137
|
+
): Promise<
|
|
138
|
+
TChannelMap[TEventName] extends (arg: any) => infer TReturn
|
|
139
|
+
? TReturn
|
|
140
|
+
: any
|
|
141
|
+
> {
|
|
142
|
+
return channel.send(
|
|
143
|
+
eventName as string,
|
|
144
|
+
args.length > 0 ? args[0] : undefined,
|
|
145
|
+
)
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
regChannel: channel.regChannel,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import type {
|
|
3
|
+
AiChatPayload,
|
|
4
|
+
AiEmbeddingPayload,
|
|
5
|
+
AiInvokeOptions,
|
|
6
|
+
AiInvokeResult,
|
|
7
|
+
AiProviderConfig,
|
|
8
|
+
AiVisionOcrPayload,
|
|
9
|
+
AiVisionOcrResult,
|
|
10
|
+
} from '../../types/intelligence'
|
|
11
|
+
import { ref } from 'vue'
|
|
12
|
+
import { useChannel } from './use-channel'
|
|
13
|
+
|
|
14
|
+
interface UseIntelligenceOptions {
|
|
15
|
+
// Reserved for future options
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface IntelligenceComposable {
|
|
19
|
+
// Core invoke functions
|
|
20
|
+
invoke: <T = any>(
|
|
21
|
+
capabilityId: string,
|
|
22
|
+
payload: any,
|
|
23
|
+
options?: AiInvokeOptions,
|
|
24
|
+
) => Promise<AiInvokeResult<T>>
|
|
25
|
+
|
|
26
|
+
// Provider testing
|
|
27
|
+
testProvider: (config: AiProviderConfig) => Promise<{
|
|
28
|
+
success: boolean
|
|
29
|
+
message: string
|
|
30
|
+
latency?: number
|
|
31
|
+
timestamp: number
|
|
32
|
+
}>
|
|
33
|
+
|
|
34
|
+
// Capability testing
|
|
35
|
+
testCapability: (params: {
|
|
36
|
+
capabilityId: string
|
|
37
|
+
providerId?: string
|
|
38
|
+
userInput?: string
|
|
39
|
+
source?: any
|
|
40
|
+
}) => Promise<{
|
|
41
|
+
ok: boolean
|
|
42
|
+
result: any
|
|
43
|
+
}>
|
|
44
|
+
|
|
45
|
+
// Get capability test metadata
|
|
46
|
+
getCapabilityTestMeta: (params: {
|
|
47
|
+
capabilityId: string
|
|
48
|
+
}) => Promise<{
|
|
49
|
+
requiresUserInput: boolean
|
|
50
|
+
inputHint: string
|
|
51
|
+
}>
|
|
52
|
+
|
|
53
|
+
// Convenient text methods
|
|
54
|
+
text: {
|
|
55
|
+
chat: (payload: AiChatPayload, options?: AiInvokeOptions) => Promise<AiInvokeResult<string>>
|
|
56
|
+
translate: (payload: { text: string, sourceLang?: string, targetLang: string }, options?: AiInvokeOptions) => Promise<AiInvokeResult<string>>
|
|
57
|
+
summarize: (payload: { text: string, maxLength?: number, style?: 'concise' | 'detailed' | 'bullet-points' }, options?: AiInvokeOptions) => Promise<AiInvokeResult<string>>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Convenient embedding methods
|
|
61
|
+
embedding: {
|
|
62
|
+
generate: (payload: AiEmbeddingPayload, options?: AiInvokeOptions) => Promise<AiInvokeResult<number[]>>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Convenient vision methods
|
|
66
|
+
vision: {
|
|
67
|
+
ocr: (payload: AiVisionOcrPayload, options?: AiInvokeOptions) => Promise<AiInvokeResult<AiVisionOcrResult>>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Loading state
|
|
71
|
+
isLoading: Ref<boolean>
|
|
72
|
+
lastError: Ref<string | null>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Intelligence Composable for Vue components
|
|
77
|
+
*
|
|
78
|
+
* Provides a reactive interface to the Intelligence module through channel communication
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const { invoke, text, isLoading, lastError } = useIntelligence()
|
|
83
|
+
*
|
|
84
|
+
* // Basic invoke
|
|
85
|
+
* const result = await invoke('text.chat', {
|
|
86
|
+
* messages: [{ role: 'user', content: 'Hello' }]
|
|
87
|
+
* })
|
|
88
|
+
*
|
|
89
|
+
* // Convenient text chat
|
|
90
|
+
* const chatResult = await text.chat({
|
|
91
|
+
* messages: [{ role: 'user', content: 'Hello' }]
|
|
92
|
+
* })
|
|
93
|
+
*
|
|
94
|
+
* // With loading state
|
|
95
|
+
* watch(isLoading, (loading) => {
|
|
96
|
+
* if (loading) console.log('AI request in progress...')
|
|
97
|
+
* })
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export function useIntelligence(_options: UseIntelligenceOptions = {}): IntelligenceComposable {
|
|
101
|
+
const isLoading = ref(false)
|
|
102
|
+
const lastError = ref<string | null>(null)
|
|
103
|
+
|
|
104
|
+
// Get the TouchChannel instance
|
|
105
|
+
const channel = useChannel()
|
|
106
|
+
|
|
107
|
+
// Helper for consistent response handling
|
|
108
|
+
interface ChannelResponse<T> {
|
|
109
|
+
ok: boolean
|
|
110
|
+
result?: T
|
|
111
|
+
error?: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function sendChannelRequest<T>(
|
|
115
|
+
eventName: string,
|
|
116
|
+
payload: any,
|
|
117
|
+
): Promise<T> {
|
|
118
|
+
const response = await channel.send<any, ChannelResponse<T>>(eventName, payload)
|
|
119
|
+
if (!response?.ok) {
|
|
120
|
+
throw new Error(response?.error || 'Intelligence request failed')
|
|
121
|
+
}
|
|
122
|
+
return response.result as T
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Wrapper function that handles loading state and errors
|
|
126
|
+
async function withLoadingState<T>(operation: () => Promise<T>): Promise<T> {
|
|
127
|
+
isLoading.value = true
|
|
128
|
+
lastError.value = null
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const result = await operation()
|
|
132
|
+
return result
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
136
|
+
lastError.value = errorMessage
|
|
137
|
+
throw error
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
isLoading.value = false
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
// Core invoke
|
|
146
|
+
invoke: <T = any>(capabilityId: string, payload: any, options?: AiInvokeOptions) =>
|
|
147
|
+
withLoadingState(() =>
|
|
148
|
+
sendChannelRequest<AiInvokeResult<T>>('intelligence:invoke', { capabilityId, payload, options }),
|
|
149
|
+
),
|
|
150
|
+
|
|
151
|
+
// Provider testing
|
|
152
|
+
testProvider: (config: AiProviderConfig) =>
|
|
153
|
+
withLoadingState(() =>
|
|
154
|
+
sendChannelRequest<{
|
|
155
|
+
success: boolean
|
|
156
|
+
message: string
|
|
157
|
+
latency?: number
|
|
158
|
+
timestamp: number
|
|
159
|
+
}>('intelligence:test-provider', { provider: config }),
|
|
160
|
+
),
|
|
161
|
+
|
|
162
|
+
// Capability testing
|
|
163
|
+
testCapability: (params: { capabilityId: string, providerId?: string, userInput?: string, source?: any }) =>
|
|
164
|
+
withLoadingState(() =>
|
|
165
|
+
sendChannelRequest<{
|
|
166
|
+
ok: boolean
|
|
167
|
+
result: any
|
|
168
|
+
}>('intelligence:test-capability', params),
|
|
169
|
+
),
|
|
170
|
+
|
|
171
|
+
// Get capability test metadata
|
|
172
|
+
getCapabilityTestMeta: (params: { capabilityId: string }) =>
|
|
173
|
+
sendChannelRequest<{
|
|
174
|
+
requiresUserInput: boolean
|
|
175
|
+
inputHint: string
|
|
176
|
+
}>('intelligence:get-capability-test-meta', params),
|
|
177
|
+
|
|
178
|
+
// Convenient text methods
|
|
179
|
+
text: {
|
|
180
|
+
chat: (payload: AiChatPayload, options?: AiInvokeOptions) =>
|
|
181
|
+
withLoadingState(() =>
|
|
182
|
+
sendChannelRequest<AiInvokeResult<string>>('intelligence:invoke', {
|
|
183
|
+
capabilityId: 'text.chat',
|
|
184
|
+
payload,
|
|
185
|
+
options,
|
|
186
|
+
}),
|
|
187
|
+
),
|
|
188
|
+
|
|
189
|
+
translate: (payload: { text: string, sourceLang?: string, targetLang: string }, options?: AiInvokeOptions) =>
|
|
190
|
+
withLoadingState(() =>
|
|
191
|
+
sendChannelRequest<AiInvokeResult<string>>('intelligence:invoke', {
|
|
192
|
+
capabilityId: 'text.translate',
|
|
193
|
+
payload,
|
|
194
|
+
options,
|
|
195
|
+
}),
|
|
196
|
+
),
|
|
197
|
+
|
|
198
|
+
summarize: (payload: { text: string, maxLength?: number, style?: 'concise' | 'detailed' | 'bullet-points' }, options?: AiInvokeOptions) =>
|
|
199
|
+
withLoadingState(() =>
|
|
200
|
+
sendChannelRequest<AiInvokeResult<string>>('intelligence:invoke', {
|
|
201
|
+
capabilityId: 'text.summarize',
|
|
202
|
+
payload,
|
|
203
|
+
options,
|
|
204
|
+
}),
|
|
205
|
+
),
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
// Convenient embedding methods
|
|
209
|
+
embedding: {
|
|
210
|
+
generate: (payload: AiEmbeddingPayload, options?: AiInvokeOptions) =>
|
|
211
|
+
withLoadingState(() =>
|
|
212
|
+
sendChannelRequest<AiInvokeResult<number[]>>('intelligence:invoke', {
|
|
213
|
+
capabilityId: 'embedding.generate',
|
|
214
|
+
payload,
|
|
215
|
+
options,
|
|
216
|
+
}),
|
|
217
|
+
),
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// Convenient vision methods
|
|
221
|
+
vision: {
|
|
222
|
+
ocr: (payload: AiVisionOcrPayload, options?: AiInvokeOptions) =>
|
|
223
|
+
withLoadingState(() =>
|
|
224
|
+
sendChannelRequest<AiInvokeResult<AiVisionOcrResult>>('intelligence:invoke', {
|
|
225
|
+
capabilityId: 'vision.ocr',
|
|
226
|
+
payload,
|
|
227
|
+
options,
|
|
228
|
+
}),
|
|
229
|
+
),
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
// Reactive state
|
|
233
|
+
isLoading,
|
|
234
|
+
lastError,
|
|
235
|
+
}
|
|
236
|
+
}
|
package/renderer/index.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
export * from '../auth'
|
|
2
|
+
export * from '../intelligence/client'
|
|
3
|
+
// Re-export Intelligence types (client-side only)
|
|
4
|
+
export * from '../types/intelligence'
|
|
5
|
+
export * from './hooks'
|
|
1
6
|
export * from './ref'
|
|
2
7
|
export * from './storage'
|
|
8
|
+
|
|
3
9
|
export * from './touch-sdk'
|
|
4
10
|
export * from './touch-sdk/utils'
|
|
5
|
-
export * from './hooks'
|
package/renderer/ref.ts
CHANGED
|
@@ -2,54 +2,50 @@ import { computed, customRef } from 'vue'
|
|
|
2
2
|
|
|
3
3
|
export function useModelWrapper(props: any, emit: any, name = 'modelValue') {
|
|
4
4
|
return computed({
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
get: () => props[name],
|
|
6
|
+
set: value => emit(`update:${name}`, value),
|
|
7
7
|
})
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export function throttleRef(value: any, time: number) {
|
|
11
|
-
|
|
12
11
|
let ts = 0
|
|
13
12
|
|
|
14
13
|
return customRef((track, trigger) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
return {
|
|
15
|
+
get() {
|
|
16
|
+
track()
|
|
17
|
+
return value
|
|
18
|
+
},
|
|
19
|
+
set(newValue) {
|
|
20
|
+
if (new Date().getTime() - ts < time)
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
value = newValue
|
|
24
|
+
track()
|
|
25
|
+
trigger()
|
|
26
|
+
ts = new Date().getTime()
|
|
27
|
+
},
|
|
28
|
+
}
|
|
30
29
|
})
|
|
31
|
-
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
export function debounceRef(value: any, delay: number) {
|
|
35
|
-
|
|
36
33
|
let timer: any
|
|
37
34
|
|
|
38
35
|
return customRef((track, trigger) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
return {
|
|
37
|
+
get() {
|
|
38
|
+
track()
|
|
39
|
+
return value
|
|
40
|
+
},
|
|
41
|
+
set(newValue) {
|
|
42
|
+
clearTimeout(timer)
|
|
43
|
+
timer = setTimeout(() => {
|
|
44
|
+
value = newValue
|
|
45
|
+
track()
|
|
46
|
+
trigger()
|
|
47
|
+
}, delay)
|
|
48
|
+
},
|
|
49
|
+
}
|
|
53
50
|
})
|
|
54
|
-
|
|
55
|
-
}
|
|
51
|
+
}
|