onin-sdk 1.3.0

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/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # Onin Plugin SDK
2
+
3
+ Onin 插件开发 SDK,提供完整的 API 支持。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install onin-plugin-sdk
9
+ ```
10
+
11
+ ## 快速开始
12
+
13
+ ```typescript
14
+ import { command, notification, storage } from 'onin-plugin-sdk';
15
+
16
+ // 注册动态命令
17
+ await command.register({
18
+ code: 'hello-world',
19
+ name: 'Hello World',
20
+ keywords: [{ name: 'hello' }],
21
+ });
22
+
23
+ // 处理命令执行
24
+ await command.handle((code, args) => {
25
+ if (code === 'hello-world') {
26
+ notification.show({
27
+ title: 'Hello!',
28
+ body: 'Welcome to Onin Plugin SDK',
29
+ });
30
+ }
31
+ });
32
+ ```
33
+
34
+ ## API 概览
35
+
36
+ ### Command API
37
+
38
+ ```typescript
39
+ // 动态注册命令
40
+ await command.register({
41
+ code: 'my-command',
42
+ name: '我的命令',
43
+ keywords: [{ name: '关键词' }],
44
+ matches: [{ type: 'text', name: '文本匹配', min: 1 }],
45
+ });
46
+
47
+ // 处理命令执行
48
+ await command.handle((code, args) => {
49
+ console.log('收到命令:', code, args);
50
+ });
51
+
52
+ // 移除动态命令
53
+ await command.remove('my-command');
54
+ ```
55
+
56
+ ### Notification API
57
+
58
+ ```typescript
59
+ await notification.show({
60
+ title: '标题',
61
+ body: '内容',
62
+ });
63
+ ```
64
+
65
+ ### Storage API
66
+
67
+ ```typescript
68
+ await storage.setItem('key', { data: 'value' });
69
+ const value = await storage.getItem('key');
70
+ await storage.removeItem('key');
71
+ ```
72
+
73
+ ### HTTP API
74
+
75
+ ```typescript
76
+ const response = await http.get('https://api.example.com/data');
77
+ const data = await http.post('https://api.example.com/create', {
78
+ body: JSON.stringify({ name: 'test' }),
79
+ });
80
+ ```
81
+
82
+ ### File System API
83
+
84
+ ```typescript
85
+ await fs.writeFile('data.json', JSON.stringify(data));
86
+ const content = await fs.readFile('data.json');
87
+ const exists = await fs.exists('data.json');
88
+ ```
89
+
90
+ ### Dialog API
91
+
92
+ ```typescript
93
+ const result = await dialog.confirm({
94
+ title: '确认',
95
+ message: '是否继续?',
96
+ });
97
+
98
+ const files = await dialog.open({
99
+ multiple: true,
100
+ filters: [{ name: 'Images', extensions: ['png', 'jpg'] }],
101
+ });
102
+ ```
103
+
104
+ ### Clipboard API
105
+
106
+ ```typescript
107
+ const text = await clipboard.readText();
108
+ await clipboard.writeText('Hello');
109
+ ```
110
+
111
+ ## 类型定义
112
+
113
+ 所有 API 都有完整的 TypeScript 类型定义,编辑器会自动提供智能提示。
114
+
115
+ ## 更多文档
116
+
117
+ 查看 [完整 API 文档](./docs) 获取更多信息。
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Test for clipboard metadata API v2 (Enhanced)
3
+ */
4
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Lifecycle API Tests
3
+ */
4
+ export {};
@@ -0,0 +1,124 @@
1
+ export type MessageContent = {
2
+ type: 'text';
3
+ text: string;
4
+ } | {
5
+ type: 'image_url';
6
+ image_url: {
7
+ url: string;
8
+ detail?: 'auto' | 'low' | 'high';
9
+ };
10
+ } | {
11
+ type: 'image_base64';
12
+ image_base64: string;
13
+ media_type?: string;
14
+ };
15
+ export interface ChatMessage {
16
+ role: 'system' | 'user' | 'assistant';
17
+ content: MessageContent[];
18
+ }
19
+ export interface ChatRequest {
20
+ model?: string;
21
+ messages: ChatMessage[];
22
+ temperature?: number;
23
+ max_tokens?: number;
24
+ stream?: boolean;
25
+ }
26
+ export interface AIProvider {
27
+ id: string;
28
+ provider_type: string;
29
+ name: string;
30
+ display_name?: string | null;
31
+ base_url: string;
32
+ default_model: string | null;
33
+ }
34
+ export interface AICapabilities {
35
+ /** Whether the provider supports image inputs (both URL and base64) */
36
+ supports_images: boolean;
37
+ /** Whether the provider supports streaming responses */
38
+ supports_streaming: boolean;
39
+ /** Whether the provider supports function calling */
40
+ supports_function_calling: boolean;
41
+ /** Maximum context window in tokens */
42
+ max_context_tokens?: number;
43
+ /** Maximum number of images allowed per message (undefined = unlimited) */
44
+ max_images_per_message?: number;
45
+ }
46
+ export interface ModelInfo {
47
+ id: string;
48
+ name: string;
49
+ description?: string;
50
+ context_window?: number;
51
+ }
52
+ export interface ValidationResult {
53
+ valid: boolean;
54
+ message?: string;
55
+ models_count?: number;
56
+ }
57
+ export declare function createTextMessage(role: 'system' | 'user' | 'assistant', text: string): ChatMessage;
58
+ export declare function createImageMessage(text: string, images: Array<string | {
59
+ url: string;
60
+ detail?: 'auto' | 'low' | 'high';
61
+ }>): ChatMessage;
62
+ /**
63
+ * Send a chat request to the configured AI provider.
64
+ * @param prompt - The user prompt or conversation history
65
+ * @param options - Additional options like model override
66
+ * @returns The AI response text
67
+ */
68
+ declare function ask(prompt: string | ChatMessage[], options?: Partial<ChatRequest>): Promise<string>;
69
+ /**
70
+ * Stream a chat response from the configured AI provider.
71
+ * @param prompt - The user prompt
72
+ * @param onChunk - Callback for each text chunk
73
+ * @param options - Additional options
74
+ * @returns Promise that resolves when stream is complete
75
+ */
76
+ declare function stream(prompt: string | ChatMessage[], onChunk: (chunk: string) => void, options?: Partial<ChatRequest>): Promise<void>;
77
+ /**
78
+ * Check if AI functionality is available (provider configured)
79
+ */
80
+ declare function isAvailable(): Promise<boolean>;
81
+ /**
82
+ * Get capabilities of the current active provider
83
+ */
84
+ declare function getCapabilities(): Promise<AICapabilities | null>;
85
+ /**
86
+ * List available models from the current active provider
87
+ */
88
+ declare function listModels(): Promise<ModelInfo[]>;
89
+ /**
90
+ * Validate a provider configuration.
91
+ * Note: Mainly for settings UI, generic plugins might not need this.
92
+ * @internal
93
+ */
94
+ declare function validateProvider(baseUrl: string, apiKey?: string): Promise<ValidationResult>;
95
+ /**
96
+ * Create a conversation manager for handling multi-turn chats
97
+ */
98
+ declare function createConversation(systemPrompt?: string): Conversation;
99
+ /**
100
+ * Helper class to manage conversation history
101
+ */
102
+ export declare class Conversation {
103
+ private messages;
104
+ constructor(systemPrompt?: string);
105
+ addMessage(message: ChatMessage): void;
106
+ ask(prompt: string | ChatMessage, options?: Partial<ChatRequest>): Promise<string>;
107
+ stream(prompt: string | ChatMessage, onChunk: (chunk: string) => void, options?: Partial<ChatRequest>): Promise<void>;
108
+ getHistory(): ChatMessage[];
109
+ clear(): void;
110
+ getLastResponse(): string | null;
111
+ }
112
+ /**
113
+ * AI namespace for interacting with configured AI providers.
114
+ */
115
+ export declare const ai: {
116
+ ask: typeof ask;
117
+ stream: typeof stream;
118
+ isAvailable: typeof isAvailable;
119
+ getCapabilities: typeof getCapabilities;
120
+ listModels: typeof listModels;
121
+ validateProvider: typeof validateProvider;
122
+ createConversation: typeof createConversation;
123
+ };
124
+ export {};
@@ -0,0 +1,346 @@
1
+ import { parseClipboardError } from '../utils/error-parser';
2
+ /**
3
+ * Reads text content from the clipboard.
4
+ * @returns Promise that resolves to the text in the clipboard, or null if the clipboard is empty or doesn't contain text.
5
+ * @throws {PluginError} With code `CLIPBOARD_UNAVAILABLE` when clipboard is not accessible
6
+ * @throws {PluginError} With code `CLIPBOARD_ACCESS_DENIED` when permission is denied
7
+ * @throws {PluginError} With code `PERMISSION_DENIED` for general permission issues
8
+ * @example
9
+ * ```typescript
10
+ * async function getClipboardText() {
11
+ * try {
12
+ * const text = await clipboard.readText();
13
+ * if (text) {
14
+ * console.log('Clipboard text:', text);
15
+ * } else {
16
+ * console.log('Clipboard is empty or does not contain text.');
17
+ * }
18
+ * } catch (error) {
19
+ * if (errorUtils.isErrorCode(error, 'CLIPBOARD_ACCESS_DENIED')) {
20
+ * console.error('Clipboard access denied');
21
+ * }
22
+ * }
23
+ * }
24
+ * ```
25
+ * @since 0.1.0
26
+ * @group API
27
+ */
28
+ export declare function readText(): Promise<string | null>;
29
+ /**
30
+ * Writes the specified text to the clipboard.
31
+ * @param text - The text to write to the clipboard.
32
+ * @returns Promise that resolves when the operation is complete.
33
+ * @throws {PluginError} With code `CLIPBOARD_UNAVAILABLE` when clipboard is not accessible
34
+ * @throws {PluginError} With code `CLIPBOARD_ACCESS_DENIED` when permission is denied
35
+ * @throws {PluginError} With code `PERMISSION_DENIED` for general permission issues
36
+ * @example
37
+ * ```typescript
38
+ * async function setClipboardText() {
39
+ * try {
40
+ * await clipboard.writeText('Hello from the plugin!');
41
+ * console.log('Text written to clipboard.');
42
+ * } catch (error) {
43
+ * console.error('Failed to write to clipboard:', error.message);
44
+ * }
45
+ * }
46
+ * ```
47
+ * @since 0.1.0
48
+ * @group API
49
+ */
50
+ export declare function writeText(text: string): Promise<void>;
51
+ /**
52
+ * Reads image data from the clipboard and returns it as a Base64 string.
53
+ * @returns Promise that resolves to the Base64 encoded string of the image, or null if the clipboard is empty or doesn't contain an image.
54
+ * @throws {PluginError} With code `CLIPBOARD_FORMAT_UNSUPPORTED` when image format is not supported
55
+ * @throws {PluginError} With code `CLIPBOARD_UNAVAILABLE` when clipboard is not accessible
56
+ * @throws {PluginError} With code `CLIPBOARD_ACCESS_DENIED` when permission is denied
57
+ * @example
58
+ * ```typescript
59
+ * async function getClipboardImage() {
60
+ * try {
61
+ * const imageBase64 = await clipboard.readImage();
62
+ * if (imageBase64) {
63
+ * const imgElement = document.createElement('img');
64
+ * imgElement.src = `data:image/png;base64,${imageBase64}`;
65
+ * document.body.appendChild(imgElement);
66
+ * } else {
67
+ * console.log('Clipboard does not contain an image.');
68
+ * }
69
+ * } catch (error) {
70
+ * if (errorUtils.isErrorCode(error, 'CLIPBOARD_FORMAT_UNSUPPORTED')) {
71
+ * console.error('Image format not supported');
72
+ * }
73
+ * }
74
+ * }
75
+ * ```
76
+ * @since 0.1.0
77
+ * @group API
78
+ */
79
+ export declare function readImage(): Promise<string | null>;
80
+ /**
81
+ * Writes image data to the clipboard.
82
+ * @param imageData - The image's Base64 encoded string or Uint8Array data.
83
+ * @returns Promise that resolves when the operation is complete.
84
+ * @throws {PluginError} With code `CLIPBOARD_FORMAT_UNSUPPORTED` when image format is not supported
85
+ * @throws {PluginError} With code `CLIPBOARD_UNAVAILABLE` when clipboard is not accessible
86
+ * @throws {PluginError} With code `CLIPBOARD_ACCESS_DENIED` when permission is denied
87
+ * @example
88
+ * ```typescript
89
+ * async function setClipboardImage(base64Data: string) {
90
+ * try {
91
+ * await clipboard.writeImage(base64Data);
92
+ * console.log('Image written to clipboard.');
93
+ * } catch (error) {
94
+ * console.error('Failed to write image to clipboard:', error.message);
95
+ * }
96
+ * }
97
+ * ```
98
+ * @since 0.1.0
99
+ * @group API
100
+ */
101
+ export declare function writeImage(imageData: string | Uint8Array): Promise<void>;
102
+ /**
103
+ * Clears all content from the clipboard.
104
+ * @returns Promise that resolves when the operation is complete.
105
+ * @throws {PluginError} With code `CLIPBOARD_UNAVAILABLE` when clipboard is not accessible
106
+ * @throws {PluginError} With code `CLIPBOARD_ACCESS_DENIED` when permission is denied
107
+ * @example
108
+ * ```typescript
109
+ * async function clearClipboard() {
110
+ * try {
111
+ * await clipboard.clear();
112
+ * console.log('Clipboard cleared.');
113
+ * } catch (error) {
114
+ * console.error('Failed to clear clipboard:', error.message);
115
+ * }
116
+ * }
117
+ * ```
118
+ * @since 0.1.0
119
+ * @group API
120
+ */
121
+ export declare function clear(): Promise<void>;
122
+ /**
123
+ * Checks if the clipboard currently contains text content.
124
+ * @returns Promise that resolves to true if the clipboard contains text, false otherwise.
125
+ * @throws {PluginError} Same error conditions as {@link readText}
126
+ * @example
127
+ * ```typescript
128
+ * async function checkText() {
129
+ * try {
130
+ * if (await clipboard.hasText()) {
131
+ * console.log('Clipboard has text.');
132
+ * const text = await clipboard.readText();
133
+ * console.log('Text content:', text);
134
+ * } else {
135
+ * console.log('Clipboard does not have text.');
136
+ * }
137
+ * } catch (error) {
138
+ * console.error('Failed to check clipboard text:', error.message);
139
+ * }
140
+ * }
141
+ * ```
142
+ * @since 0.1.0
143
+ * @group API
144
+ */
145
+ export declare function hasText(): Promise<boolean>;
146
+ /**
147
+ * Checks if the clipboard currently contains image content.
148
+ * @returns Promise that resolves to true if the clipboard contains an image, false otherwise.
149
+ * @throws {PluginError} Same error conditions as {@link readImage}
150
+ * @example
151
+ * ```typescript
152
+ * async function checkImage() {
153
+ * try {
154
+ * if (await clipboard.hasImage()) {
155
+ * console.log('Clipboard has an image.');
156
+ * const imageData = await clipboard.readImage();
157
+ * console.log('Image data available:', !!imageData);
158
+ * } else {
159
+ * console.log('Clipboard does not have an image.');
160
+ * }
161
+ * } catch (error) {
162
+ * console.error('Failed to check clipboard image:', error.message);
163
+ * }
164
+ * }
165
+ * ```
166
+ * @since 0.1.0
167
+ * @group API
168
+ */
169
+ export declare function hasImage(): Promise<boolean>;
170
+ /**
171
+ * Copies text to the clipboard, alias for `writeText`.
172
+ * @param text - The text to copy.
173
+ * @returns Promise that resolves when the operation is complete.
174
+ * @throws {PluginError} Same error conditions as {@link writeText}
175
+ * @see {@link writeText} - For detailed error information
176
+ * @since 0.1.0
177
+ * @group API
178
+ */
179
+ export declare function copy(text: string): Promise<void>;
180
+ /**
181
+ * Pastes text content from the clipboard, alias for `readText`.
182
+ * @returns Promise that resolves to the text in the clipboard, or null if empty.
183
+ * @throws {PluginError} Same error conditions as {@link readText}
184
+ * @see {@link readText} - For detailed error information
185
+ * @since 0.1.0
186
+ * @group API
187
+ */
188
+ export declare function paste(): Promise<string | null>;
189
+ /**
190
+ * Clipboard content type enumeration
191
+ * @since 0.1.0
192
+ * @group Types
193
+ */
194
+ export type ClipboardContentType = 'text' | 'image' | 'files' | 'empty';
195
+ /**
196
+ * File information in clipboard
197
+ * @interface ClipboardFile
198
+ * @since 0.1.0
199
+ * @group Types
200
+ */
201
+ export interface ClipboardFile {
202
+ /** Full file path */
203
+ path: string;
204
+ /** File name */
205
+ name: string;
206
+ /** Whether this is a directory */
207
+ is_directory: boolean;
208
+ }
209
+ /**
210
+ * Enhanced metadata about clipboard content including type, timestamp, and age information
211
+ * @interface ClipboardMetadata
212
+ * @since 0.1.0
213
+ * @group Types
214
+ */
215
+ export interface ClipboardMetadata {
216
+ /** The text content in the clipboard, or null if no text */
217
+ text: string | null;
218
+ /** List of file paths if clipboard contains files, or null if no files */
219
+ files: ClipboardFile[] | null;
220
+ /** The type of content in the clipboard */
221
+ contentType: ClipboardContentType;
222
+ /**
223
+ * Unix timestamp (in seconds) when the clipboard content was last updated.
224
+ *
225
+ * Note: This timestamp is independent from the app's auto_clear_time_limit setting.
226
+ * Even if the app clears its internal state, this timestamp will still reflect
227
+ * when the system clipboard was actually modified.
228
+ *
229
+ * May be null only if:
230
+ * - Clipboard monitoring hasn't started yet
231
+ * - The clipboard has never been modified since app start
232
+ */
233
+ timestamp: number | null;
234
+ /**
235
+ * Age of the clipboard content in seconds (time since it was copied).
236
+ * Calculated as: current_time - timestamp.
237
+ * Will be null if timestamp is null.
238
+ */
239
+ age: number | null;
240
+ }
241
+ /**
242
+ * Gets comprehensive clipboard metadata including content type, timestamp, and age.
243
+ * This enhanced API provides detailed information about clipboard content:
244
+ * - Content type detection (text, image, files, or empty)
245
+ * - Text content (if available)
246
+ * - Image detection
247
+ * - File paths (if files were copied)
248
+ * - Timestamp when content was copied
249
+ * - Age in seconds (automatically calculated)
250
+ *
251
+ * @returns Promise that resolves to comprehensive clipboard metadata
252
+ * @throws {PluginError} Same error conditions as {@link readText}
253
+ * @example
254
+ * ```typescript
255
+ * // Basic usage - check content type and age
256
+ * const metadata = await clipboard.getMetadata();
257
+ * console.log('Content type:', metadata.contentType);
258
+ * console.log('Age:', metadata.age, 'seconds');
259
+ *
260
+ * // Handle different content types
261
+ * switch (metadata.contentType) {
262
+ * case 'text':
263
+ * console.log('Text:', metadata.text);
264
+ * break;
265
+ * case 'image':
266
+ * console.log('Clipboard contains an image');
267
+ * break;
268
+ * case 'files':
269
+ * console.log('Files:', metadata.files?.map(f => f.name));
270
+ * break;
271
+ * case 'empty':
272
+ * console.log('Clipboard is empty');
273
+ * break;
274
+ * }
275
+ *
276
+ * // Time-based filtering using age
277
+ * if (metadata.age !== null && metadata.age < 10) {
278
+ * console.log('Content is fresh (less than 10 seconds old)');
279
+ * await processContent(metadata);
280
+ * }
281
+ *
282
+ * // Check for image
283
+ * if (metadata.contentType === 'image') {
284
+ * console.log('Image detected in clipboard');
285
+ * }
286
+ *
287
+ * if (metadata.files && metadata.files.length > 0) {
288
+ * console.log('Files copied:', metadata.files.length);
289
+ * metadata.files.forEach(file => {
290
+ * console.log(`- ${file.name} (${file.is_directory ? 'dir' : 'file'})`);
291
+ * });
292
+ * }
293
+ * ```
294
+ * @since 0.1.0
295
+ * @group API
296
+ */
297
+ export declare function getMetadata(): Promise<ClipboardMetadata>;
298
+ /**
299
+ * Clipboard API namespace - provides functions for interacting with the system clipboard
300
+ *
301
+ * Supports reading and writing text and image data to/from the system clipboard.
302
+ * All operations require appropriate permissions and handle various clipboard states gracefully.
303
+ *
304
+ * @namespace clipboard
305
+ * @version 0.1.0
306
+ * @since 0.1.0
307
+ * @group API
308
+ * @see {@link parseClipboardError} - For error handling utilities
309
+ * @example
310
+ * ```typescript
311
+ * import { clipboard } from 'onin-plugin-sdk';
312
+ *
313
+ * // Read text from clipboard
314
+ * const text = await clipboard.readText();
315
+ *
316
+ * // Write text to clipboard
317
+ * await clipboard.writeText('Hello World');
318
+ *
319
+ * // Check if clipboard has content
320
+ * if (await clipboard.hasText()) {
321
+ * console.log('Clipboard has text content');
322
+ * }
323
+ *
324
+ * // Get metadata with timestamp
325
+ * const metadata = await clipboard.getMetadata();
326
+ * console.log('Content age:', Date.now() / 1000 - metadata.timestamp);
327
+ * ```
328
+ */
329
+ export declare const clipboard: {
330
+ /** Core methods */
331
+ readText: typeof readText;
332
+ writeText: typeof writeText;
333
+ readImage: typeof readImage;
334
+ writeImage: typeof writeImage;
335
+ clear: typeof clear;
336
+ /** Check methods */
337
+ hasText: typeof hasText;
338
+ hasImage: typeof hasImage;
339
+ /** Metadata methods */
340
+ getMetadata: typeof getMetadata;
341
+ /** Convenience methods */
342
+ copy: typeof copy;
343
+ paste: typeof paste;
344
+ /** Error handling tools */
345
+ parseClipboardError: typeof parseClipboardError;
346
+ };