@talex-touch/utils 1.0.31 → 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 (112) hide show
  1. package/animation/window-node.ts +15 -12
  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 +4 -4
  7. package/auth/useClerkProvider.ts +3 -2
  8. package/channel/index.ts +23 -22
  9. package/common/file-scan-constants.ts +137 -121
  10. package/common/file-scan-utils.ts +48 -27
  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 +5 -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 +14 -6
  19. package/common/utils/index.ts +62 -52
  20. package/common/utils/polling.ts +87 -84
  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 +254 -229
  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 +328 -266
  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 +5 -4
  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 +96 -82
  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 +1 -1
  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 +8 -7
  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 +147 -141
  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 -2
  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 +222 -114
  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 -102
  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/index.ts +3 -1
  100. package/types/intelligence.ts +413 -0
  101. package/types/modules/base.ts +16 -16
  102. package/types/modules/index.ts +1 -1
  103. package/types/modules/module-lifecycle.ts +21 -21
  104. package/types/modules/module-manager.ts +11 -11
  105. package/types/modules/module.ts +16 -16
  106. package/types/storage.ts +0 -1
  107. package/types/touch-app-core.ts +32 -32
  108. package/types/update.ts +79 -21
  109. package/core-box/README.md +0 -218
  110. package/core-box/builder/tuff-builder.example.ts.bak +0 -258
  111. package/core-box/run-tests.sh +0 -7
  112. package/core-box/search.ts +0 -1
@@ -47,7 +47,8 @@ export class ClipboardHelper {
47
47
  for (i = 0; i < length; i++) {
48
48
  uuid[i] = chars[0 | (Math.random() * radix)]
49
49
  }
50
- } else {
50
+ }
51
+ else {
51
52
  let r: number
52
53
  uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
53
54
  uuid[14] = '4'
@@ -75,7 +76,8 @@ export class ClipboardHelper {
75
76
  // Handle multiple files
76
77
  const tagContent = clipboard.read('NSFilenamesPboardType').match(/<string>.*<\/string>/g)
77
78
  filePath = tagContent ? tagContent.map(item => item.replace(/<string>|<\/string>/g, '')) : []
78
- } else {
79
+ }
80
+ else {
79
81
  // Handle single file
80
82
  const clipboardImage = clipboard.readImage('clipboard')
81
83
  if (!clipboardImage.isEmpty()) {
@@ -84,10 +86,11 @@ export class ClipboardHelper {
84
86
  const fileInfo: ClipboardFileInfo = {
85
87
  buffer: png,
86
88
  mimetype: 'image/png',
87
- originalname: this.generateUuid(8, 16) + '.png'
89
+ originalname: `${this.generateUuid(8, 16)}.png`,
88
90
  }
89
91
  filePath = [fileInfo]
90
- } else {
92
+ }
93
+ else {
91
94
  // Handle single file path
92
95
  const fileUrl = clipboard.read('public.file-url')
93
96
  if (fileUrl) {
@@ -115,7 +118,7 @@ export class ClipboardHelper {
115
118
  .join('')
116
119
  .replace(/\\/g, '\\\\')
117
120
 
118
- const drivePrefix = formatFilePathStr.match(/[a-zA-Z]:\\/)
121
+ const drivePrefix = formatFilePathStr.match(/[a-z]:\\/i)
119
122
 
120
123
  if (drivePrefix) {
121
124
  const drivePrefixIndex = formatFilePathStr.indexOf(drivePrefix[0])
@@ -127,7 +130,8 @@ export class ClipboardHelper {
127
130
  .filter(item => item)
128
131
  .map(item => drivePrefix[0] + item)
129
132
  }
130
- } else {
133
+ }
134
+ else {
131
135
  // Handle single file
132
136
  const clipboardImage = clipboard.readImage('clipboard')
133
137
  if (!clipboardImage.isEmpty()) {
@@ -136,17 +140,19 @@ export class ClipboardHelper {
136
140
  const fileInfo: ClipboardFileInfo = {
137
141
  buffer: png,
138
142
  mimetype: 'image/png',
139
- originalname: this.generateUuid(8, 16) + '.png'
143
+ originalname: `${this.generateUuid(8, 16)}.png`,
140
144
  }
141
145
  filePath = [fileInfo]
142
- } else {
146
+ }
147
+ else {
143
148
  // Handle single file path
144
149
  try {
145
- const fileName = clipboard.readBuffer('FileNameW').toString('ucs2').replace(RegExp(String.fromCharCode(0), 'g'), '')
150
+ const fileName = clipboard.readBuffer('FileNameW').toString('ucs2').replace(new RegExp(String.fromCharCode(0), 'g'), '')
146
151
  if (fileName) {
147
152
  filePath = [fileName]
148
153
  }
149
- } catch (error) {
154
+ }
155
+ catch (error) {
150
156
  // Ignore read errors for non-file clipboard content
151
157
  }
152
158
  }
@@ -183,10 +189,12 @@ export class ClipboardHelper {
183
189
  try {
184
190
  if (this.isMac) {
185
191
  return this.getClipboardFilesMac()
186
- } else {
192
+ }
193
+ else {
187
194
  return this.getClipboardFilesWindows()
188
195
  }
189
- } catch (error) {
196
+ }
197
+ catch (error) {
190
198
  console.error('Failed to read clipboard files:', error)
191
199
  return []
192
200
  }
@@ -1,20 +1,20 @@
1
+ import path from 'node:path'
1
2
  import { net } from 'electron'
2
3
  import fse from 'fs-extra'
3
- import path from 'path'
4
4
 
5
5
  interface DownloadItem {
6
- url: string;
7
- filename: string;
8
- apply?: (filePath: string) => void;
6
+ url: string
7
+ filename: string
8
+ apply?: (filePath: string) => void
9
9
  }
10
10
 
11
11
  export class DownloadManager {
12
- private basePath: string;
13
- private downloadQueue: DownloadItem[] = [];
14
- private isDownloading = false;
12
+ private basePath: string
13
+ private downloadQueue: DownloadItem[] = []
14
+ private isDownloading = false
15
15
 
16
16
  constructor(basePath: string = '') {
17
- this.basePath = basePath;
17
+ this.basePath = basePath
18
18
  }
19
19
 
20
20
  /**
@@ -22,9 +22,9 @@ export class DownloadManager {
22
22
  * @param item The download item object
23
23
  */
24
24
  addDownload(item: DownloadItem): void {
25
- this.downloadQueue.push(item);
25
+ this.downloadQueue.push(item)
26
26
  if (!this.isDownloading) {
27
- this.processQueue();
27
+ this.processQueue()
28
28
  }
29
29
  }
30
30
 
@@ -33,9 +33,9 @@ export class DownloadManager {
33
33
  * @param items Array of download items
34
34
  */
35
35
  addDownloads(items: DownloadItem[]): void {
36
- this.downloadQueue.push(...items);
36
+ this.downloadQueue.push(...items)
37
37
  if (!this.isDownloading) {
38
- this.processQueue();
38
+ this.processQueue()
39
39
  }
40
40
  }
41
41
 
@@ -44,26 +44,27 @@ export class DownloadManager {
44
44
  */
45
45
  private async processQueue(): Promise<void> {
46
46
  if (this.downloadQueue.length === 0) {
47
- this.isDownloading = false;
48
- return;
47
+ this.isDownloading = false
48
+ return
49
49
  }
50
50
 
51
- this.isDownloading = true;
52
- const item = this.downloadQueue.shift()!;
51
+ this.isDownloading = true
52
+ const item = this.downloadQueue.shift()!
53
53
 
54
54
  try {
55
- console.log(`[DownloadManager] Starting to download ${item.filename} from ${item.url}`);
56
- const filePath = await this.downloadFile(item.url, item.filename);
57
- console.log(`[DownloadManager] Download ${item.filename} completed`);
55
+ console.log(`[DownloadManager] Starting to download ${item.filename} from ${item.url}`)
56
+ const filePath = await this.downloadFile(item.url, item.filename)
57
+ console.log(`[DownloadManager] Download ${item.filename} completed`)
58
58
 
59
59
  if (item.apply) {
60
- item.apply(filePath);
60
+ item.apply(filePath)
61
61
  }
62
- } catch (error) {
63
- console.error(`[DownloadManager] Download ${item.filename} failed:`, error);
62
+ }
63
+ catch (error) {
64
+ console.error(`[DownloadManager] Download ${item.filename} failed:`, error)
64
65
  }
65
66
 
66
- this.processQueue();
67
+ this.processQueue()
67
68
  }
68
69
 
69
70
  /**
@@ -74,45 +75,45 @@ export class DownloadManager {
74
75
  */
75
76
  private downloadFile(url: string, filename: string): Promise<string> {
76
77
  return new Promise((resolve, reject) => {
77
- const request = net.request(url);
78
- const filePath = this.basePath ? path.join(this.basePath, filename) : filename;
78
+ const request = net.request(url)
79
+ const filePath = this.basePath ? path.join(this.basePath, filename) : filename
79
80
 
80
- console.log(`[DownloadManager] File download request sent for ${filename}.`);
81
+ console.log(`[DownloadManager] File download request sent for ${filename}.`)
81
82
 
82
83
  request.addListener('error', (error) => {
83
- console.error(`[DownloadManager] Download request error for ${filename}:`, error);
84
- reject(error);
85
- });
84
+ console.error(`[DownloadManager] Download request error for ${filename}:`, error)
85
+ reject(error)
86
+ })
86
87
 
87
88
  request.addListener('response', (response) => {
88
- fse.createFileSync(filePath);
89
+ fse.createFileSync(filePath)
89
90
 
90
91
  response.addListener('data', (chunk: any) => {
91
- console.log(`[DownloadManager] Downloading ${filename}...`);
92
- fse.appendFile(filePath, chunk, 'utf8');
93
- });
92
+ console.log(`[DownloadManager] Downloading ${filename}...`)
93
+ fse.appendFile(filePath, chunk, 'utf8')
94
+ })
94
95
 
95
96
  response.addListener('end', () => {
96
- console.log(`[DownloadManager] Download ${filename} finished.`);
97
- resolve(filePath);
98
- });
99
- });
97
+ console.log(`[DownloadManager] Download ${filename} finished.`)
98
+ resolve(filePath)
99
+ })
100
+ })
100
101
 
101
- request.end();
102
- });
102
+ request.end()
103
+ })
103
104
  }
104
105
 
105
106
  /**
106
107
  * Clear the download queue
107
108
  */
108
109
  clearQueue(): void {
109
- this.downloadQueue = [];
110
+ this.downloadQueue = []
110
111
  }
111
112
 
112
113
  /**
113
114
  * Get the number of items in the download queue
114
115
  */
115
116
  getQueueLength(): number {
116
- return this.downloadQueue.length;
117
+ return this.downloadQueue.length
117
118
  }
118
- }
119
+ }
@@ -1,5 +1,6 @@
1
- import { exec, ExecException } from 'child_process'
2
- import { platform } from 'process'
1
+ import type { ExecException } from 'node:child_process'
2
+ import { exec } from 'node:child_process'
3
+ import { platform } from 'node:process'
3
4
 
4
5
  export interface IGlobalPkgResult {
5
6
  exist: boolean
@@ -14,35 +15,34 @@ export function checkGlobalPackageExist(packageName: string): Promise<IGlobalPkg
14
15
  if (error) {
15
16
  reject({
16
17
  exits: false,
17
- error: error
18
- });
19
- return;
18
+ error,
19
+ })
20
+ return
20
21
  }
21
22
  if (stderr) {
22
23
  reject({
23
24
  exits: false,
24
- error: stderr
25
- });
26
- return;
25
+ error: stderr,
26
+ })
27
+ return
27
28
  }
28
29
 
29
- const lines = stdout.split('\n');
30
- const lastLine = lines[lines.length - 3];
31
- const match = lastLine.match(/(\S+)@(\S+)/);
30
+ const lines = stdout.split('\n')
31
+ const lastLine = lines[lines.length - 3]
32
+ const match = lastLine.match(/(\S+)@(\S+)/)
32
33
  if (match) {
33
34
  resolve({
34
35
  exist: true,
35
36
  name: match[1],
36
- version: match[2]
37
- } as IGlobalPkgResult);
38
- return;
37
+ version: match[2],
38
+ } as IGlobalPkgResult)
39
+ return
39
40
  }
40
41
 
41
42
  resolve({
42
- exist: false
43
+ exist: false,
43
44
  } as IGlobalPkgResult)
44
-
45
- });
45
+ })
46
46
  })
47
47
  }
48
48
 
@@ -50,7 +50,8 @@ export function checkGlobalPackageExist(packageName: string): Promise<IGlobalPkg
50
50
  export function getNpmVersion(): Promise<string | null> {
51
51
  return new Promise((resolve) => {
52
52
  exec(`npm --version`, (error, stdout, stderr) => {
53
- if (error || stderr) resolve(null)
53
+ if (error || stderr)
54
+ resolve(null)
54
55
 
55
56
  resolve(stdout.trim())
56
57
  })
@@ -1,8 +1,8 @@
1
- import { fileParserRegistry } from './registry'
2
1
  import { textFileParser } from './parsers/text-parser'
2
+ import { fileParserRegistry } from './registry'
3
3
 
4
4
  fileParserRegistry.register(textFileParser)
5
5
 
6
- export * from './types'
7
6
  export * from './registry'
7
+ export * from './types'
8
8
  export { textFileParser }
@@ -1,11 +1,11 @@
1
- import fs from 'fs/promises'
2
- import path from 'path'
3
- import {
1
+ import type {
4
2
  FileParser,
5
3
  FileParserContext,
6
4
  FileParserProgress,
7
- FileParserResult
5
+ FileParserResult,
8
6
  } from '../types'
7
+ import fs from 'node:fs/promises'
8
+ import path from 'node:path'
9
9
 
10
10
  const TEXTUAL_EXTENSIONS = new Set(
11
11
  [
@@ -48,8 +48,8 @@ const TEXTUAL_EXTENSIONS = new Set(
48
48
  '.fish',
49
49
  '.bat',
50
50
  '.ps1',
51
- '.sql'
52
- ].map((ext) => ext.toLowerCase())
51
+ '.sql',
52
+ ].map(ext => ext.toLowerCase()),
53
53
  )
54
54
 
55
55
  export class TextFileParser implements FileParser {
@@ -59,7 +59,7 @@ export class TextFileParser implements FileParser {
59
59
 
60
60
  async parse(
61
61
  context: FileParserContext,
62
- onProgress?: (progress: FileParserProgress) => void
62
+ onProgress?: (progress: FileParserProgress) => void,
63
63
  ): Promise<FileParserResult> {
64
64
  const { filePath, extension, size, maxBytes } = context
65
65
  if (maxBytes && size > maxBytes) {
@@ -69,15 +69,15 @@ export class TextFileParser implements FileParser {
69
69
  totalBytes: size,
70
70
  processedBytes: 0,
71
71
  warnings: [
72
- `File size ${(size / (1024 * 1024)).toFixed(2)}MB exceeds limit ${(maxBytes / (1024 * 1024)).toFixed(2)}MB`
73
- ]
72
+ `File size ${(size / (1024 * 1024)).toFixed(2)}MB exceeds limit ${(maxBytes / (1024 * 1024)).toFixed(2)}MB`,
73
+ ],
74
74
  }
75
75
  }
76
76
 
77
77
  if (!TEXTUAL_EXTENSIONS.has(extension)) {
78
78
  return {
79
79
  status: 'skipped',
80
- reason: 'unsupported-extension'
80
+ reason: 'unsupported-extension',
81
81
  }
82
82
  }
83
83
 
@@ -92,15 +92,16 @@ export class TextFileParser implements FileParser {
92
92
  content,
93
93
  metadata: {
94
94
  length: content.length,
95
- basename: path.basename(filePath)
95
+ basename: path.basename(filePath),
96
96
  },
97
97
  processedBytes: size,
98
- totalBytes: size
98
+ totalBytes: size,
99
99
  }
100
- } catch (error) {
100
+ }
101
+ catch (error) {
101
102
  return {
102
103
  status: 'failed',
103
- reason: error instanceof Error ? error.message : 'unknown-error'
104
+ reason: error instanceof Error ? error.message : 'unknown-error',
104
105
  }
105
106
  }
106
107
  }
@@ -1,9 +1,9 @@
1
- import {
1
+ import type {
2
2
  FileParser,
3
3
  FileParserContext,
4
4
  FileParserProgress,
5
5
  FileParserResult,
6
- FileParserSelectionOptions
6
+ FileParserSelectionOptions,
7
7
  } from './types'
8
8
 
9
9
  interface RegisteredParser {
@@ -17,7 +17,7 @@ export class FileParserRegistry {
17
17
 
18
18
  register(parser: FileParser): void {
19
19
  const extensions = new Set(
20
- Array.from(parser.supportedExtensions).map((ext) => ext.trim().toLowerCase())
20
+ Array.from(parser.supportedExtensions).map(ext => ext.trim().toLowerCase()),
21
21
  )
22
22
  if (extensions.size === 0) {
23
23
  throw new Error(`[FileParserRegistry] Parser ${parser.id} registered without extensions`)
@@ -35,7 +35,8 @@ export class FileParserRegistry {
35
35
  }
36
36
 
37
37
  getParsersForExtension(extension: string): FileParser[] {
38
- if (!extension) return []
38
+ if (!extension)
39
+ return []
39
40
  const normalized = extension.toLowerCase()
40
41
  return this.parsers
41
42
  .filter(({ extensions }) => extensions.has(normalized))
@@ -54,7 +55,7 @@ export class FileParserRegistry {
54
55
 
55
56
  async parseWithBestParser(
56
57
  context: FileParserContext,
57
- onProgress?: (progress: FileParserProgress) => void
58
+ onProgress?: (progress: FileParserProgress) => void,
58
59
  ): Promise<FileParserResult | null> {
59
60
  const candidates = this.getParsersForExtension(context.extension)
60
61
  const allParsers = context.extension !== '*' ? candidates : []
@@ -76,11 +77,12 @@ export class FileParserRegistry {
76
77
  if (result.status !== 'skipped') {
77
78
  return result
78
79
  }
79
- } catch (error) {
80
+ }
81
+ catch (error) {
80
82
  console.error(`[FileParserRegistry] Parser ${parser.id} failed:`, error)
81
83
  return {
82
84
  status: 'failed',
83
- reason: error instanceof Error ? error.message : 'unknown-error'
85
+ reason: error instanceof Error ? error.message : 'unknown-error',
84
86
  }
85
87
  }
86
88
  }
@@ -41,11 +41,11 @@ export interface FileParser {
41
41
  /** Higher priority parsers win when multiple support the same extension */
42
42
  readonly priority?: number
43
43
  readonly supportedExtensions: string[] | Set<string>
44
- canParse?(context: FileParserContext): boolean | Promise<boolean>
45
- parse(
44
+ canParse?: (context: FileParserContext) => boolean | Promise<boolean>
45
+ parse: (
46
46
  context: FileParserContext,
47
- onProgress?: (progress: FileParserProgress) => void
48
- ): Promise<FileParserResult>
47
+ onProgress?: (progress: FileParserProgress) => void,
48
+ ) => Promise<FileParserResult>
49
49
  }
50
50
 
51
51
  export interface FileParserSelectionOptions {
package/electron/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './clipboard-helper'
2
2
  export * from './download-manager'
3
- export * from './env-tool'
3
+ export * from './env-tool'
package/eventbus/index.ts CHANGED
@@ -1,17 +1,17 @@
1
- export type EventHandler = (event: ITouchEvent) => void;
1
+ export type EventHandler = (event: ITouchEvent) => void
2
2
 
3
3
  export interface EventHandlerWrapper {
4
4
  /**
5
5
  * Event handler
6
6
  */
7
- handler: EventHandler;
7
+ handler: EventHandler
8
8
 
9
9
  /**
10
10
  * Event type
11
11
  * @see EventType
12
12
  * @default EventType.PERSIST (must be, if implements)
13
13
  */
14
- type?: EventType;
14
+ type?: EventType
15
15
  }
16
16
 
17
17
  export enum EventType {
@@ -23,16 +23,16 @@ export interface ITouchEvent<E = any> {
23
23
  /**
24
24
  * Event name
25
25
  */
26
- name: E;
26
+ name: E
27
27
 
28
28
  /**
29
29
  * Event data
30
30
  */
31
- data?: any;
31
+ data?: any
32
32
  }
33
33
 
34
34
  export interface ITouchEventBus<E> {
35
- map: Map<E, Set<EventHandlerWrapper>>;
35
+ map: Map<E, Set<EventHandlerWrapper>>
36
36
 
37
37
  /**
38
38
  * Subscribe touch-app events (any kind of events extends from TouchEvent)
@@ -40,7 +40,7 @@ export interface ITouchEventBus<E> {
40
40
  * @param handler Event handler (extends from EventHandler)
41
41
  * @returns true if the event was added, otherwise false
42
42
  */
43
- on(event: E, handler: EventHandler): boolean | void;
43
+ on: (event: E, handler: EventHandler) => boolean | void
44
44
 
45
45
  /**
46
46
  * Subscribe touch-app events (any kind of events extends from TouchEvent)
@@ -48,7 +48,7 @@ export interface ITouchEventBus<E> {
48
48
  * @param handler Event handler (extends from EventHandler)
49
49
  * @returns true if the event was added, otherwise false
50
50
  */
51
- once(event: E, handler: EventHandler): boolean | void;
51
+ once: (event: E, handler: EventHandler) => boolean | void
52
52
 
53
53
  /**
54
54
  * UnSubscribe touch-app events (any kind of events extends from TouchEvent)
@@ -61,19 +61,19 @@ export interface ITouchEventBus<E> {
61
61
  * console.log(event)
62
62
  * }
63
63
  */
64
- off(event: E, handler: EventHandler): boolean;
64
+ off: (event: E, handler: EventHandler) => boolean
65
65
 
66
66
  /**
67
67
  * UnSubscribe touch-app events all matched (any kind of events extends from TouchEvent)
68
68
  * @param event EventName (extends from TouchEvent)
69
69
  * @returns true if the event was added, otherwise false
70
70
  */
71
- offAll(event: E): boolean;
71
+ offAll: (event: E) => boolean
72
72
 
73
73
  /**
74
74
  * Emit touch-app events (any kind of events extends from TouchEvent)
75
75
  * @param event EventName (extends from TouchEvent)
76
76
  * @param data Event data (extends from TouchEvent)
77
77
  */
78
- emit<T extends ITouchEvent<E>>(event: E, data: T): void;
78
+ emit: <T extends ITouchEvent<E>>(event: E, data: T) => void
79
79
  }
package/index.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  // export * from './auth' // Renderer-only, use @talex-touch/utils/renderer instead
2
2
  export * from './base'
3
+ export * from './channel'
3
4
  export * from './common'
4
- export * from './plugin'
5
5
  export * from './core-box'
6
- export * from './channel'
7
- export * from './types'
8
- export * from './types/icon'
9
6
  export * from './eventbus'
7
+ export * from './intelligence'
8
+ export * from './plugin'
10
9
  export * from './preload'
10
+ export * from './types'
11
11
  export * from './types/download'
12
+ export * from './types/icon'
12
13
  export * from './types/update'
@@ -0,0 +1,87 @@
1
+ import type { AiInvokeOptions, AiInvokeResult, AiProviderConfig } from '../types/intelligence'
2
+
3
+ export interface IntelligenceClientChannel {
4
+ send: (eventName: string, payload: unknown) => Promise<any>
5
+ }
6
+
7
+ export type IntelligenceChannelResolver = () => IntelligenceClientChannel | null | undefined
8
+
9
+ const defaultResolvers: IntelligenceChannelResolver[] = [
10
+ () => {
11
+ if (typeof globalThis === 'undefined')
12
+ return null
13
+ const maybe
14
+ = (globalThis as any).touchChannel
15
+ || (globalThis as any).$touchChannel
16
+ || (globalThis as any).channel
17
+ || (globalThis as any).window?.touchChannel
18
+ || (globalThis as any).window?.$touchChannel
19
+ return maybe ?? null
20
+ },
21
+ ]
22
+
23
+ export function resolveIntelligenceChannel(resolvers: IntelligenceChannelResolver[] = defaultResolvers): IntelligenceClientChannel | null {
24
+ for (const resolver of resolvers) {
25
+ try {
26
+ const channel = resolver()
27
+ if (channel) {
28
+ return channel
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.warn('[Intelligence Client] Channel resolver failed:', error)
33
+ }
34
+ }
35
+ return null
36
+ }
37
+
38
+ interface ChannelResponse<T> {
39
+ ok: boolean
40
+ result?: T
41
+ error?: string
42
+ }
43
+
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')
48
+ }
49
+ return response.result as T
50
+ }
51
+
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 }>
57
+ }
58
+
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.')
63
+ }
64
+
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
+ },
86
+ }
87
+ }
@@ -0,0 +1 @@
1
+ export * from './client'