illuma-agents 1.0.42 → 1.0.43
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/dist/cjs/main.cjs +6 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/stream.cjs +14 -0
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/DesktopTools.cjs +295 -0
- package/dist/cjs/tools/DesktopTools.cjs.map +1 -0
- package/dist/esm/main.mjs +1 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/stream.mjs +14 -0
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/DesktopTools.mjs +289 -0
- package/dist/esm/tools/DesktopTools.mjs.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/tools/DesktopTools.d.ts +104 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/stream.ts +17 -0
- package/src/tools/DesktopTools.ts +552 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
|
+
/**
|
|
3
|
+
* Desktop tool names - keep in sync with Ranger Desktop Electron app
|
|
4
|
+
* These tools execute locally in the Electron app, NOT on the server
|
|
5
|
+
*/
|
|
6
|
+
export declare const EDesktopTools: {
|
|
7
|
+
readonly SCREENSHOT: "computer_screenshot";
|
|
8
|
+
readonly CLICK: "computer_click";
|
|
9
|
+
readonly DOUBLE_CLICK: "computer_double_click";
|
|
10
|
+
readonly RIGHT_CLICK: "computer_right_click";
|
|
11
|
+
readonly TYPE: "computer_type";
|
|
12
|
+
readonly KEY: "computer_key";
|
|
13
|
+
readonly KEY_COMBO: "computer_key_combo";
|
|
14
|
+
readonly SCROLL: "computer_scroll";
|
|
15
|
+
readonly DRAG: "computer_drag";
|
|
16
|
+
readonly GET_ACTIVE_WINDOW: "computer_get_active_window";
|
|
17
|
+
readonly GET_MOUSE_POSITION: "computer_get_mouse_position";
|
|
18
|
+
readonly CLIPBOARD_READ: "clipboard_read";
|
|
19
|
+
readonly CLIPBOARD_WRITE: "clipboard_write";
|
|
20
|
+
readonly CLIPBOARD_PASTE: "clipboard_paste";
|
|
21
|
+
readonly WAIT: "computer_wait";
|
|
22
|
+
};
|
|
23
|
+
export type DesktopToolName = (typeof EDesktopTools)[keyof typeof EDesktopTools];
|
|
24
|
+
/**
|
|
25
|
+
* Callback function type for waiting on desktop action results
|
|
26
|
+
* This allows the server (Ranger) to provide a callback that waits for the Electron app
|
|
27
|
+
* to POST results back to the server before returning to the LLM.
|
|
28
|
+
*
|
|
29
|
+
* @param action - The desktop action (click, type, screenshot, etc.)
|
|
30
|
+
* @param args - Arguments for the action
|
|
31
|
+
* @param toolCallId - Unique ID for this tool call (from config.toolCall.id)
|
|
32
|
+
* @returns Promise that resolves with the actual desktop result
|
|
33
|
+
*/
|
|
34
|
+
export type DesktopToolCallback = (action: string, args: Record<string, unknown>, toolCallId: string) => Promise<DesktopActionResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Result returned from desktop action execution
|
|
37
|
+
*/
|
|
38
|
+
export interface DesktopActionResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
error?: string;
|
|
41
|
+
screenshot?: {
|
|
42
|
+
base64: string;
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
};
|
|
46
|
+
activeWindow?: {
|
|
47
|
+
title: string;
|
|
48
|
+
app: string;
|
|
49
|
+
bounds?: {
|
|
50
|
+
x: number;
|
|
51
|
+
y: number;
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
mousePosition?: {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
};
|
|
60
|
+
clipboard?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if desktop capability is available based on request headers or context
|
|
64
|
+
* The Ranger Desktop Electron app sets these headers when connected:
|
|
65
|
+
* - X-Ranger-Desktop: true
|
|
66
|
+
* - X-Ranger-Desktop-Capable: true
|
|
67
|
+
*/
|
|
68
|
+
export declare function hasDesktopCapability(req?: {
|
|
69
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
70
|
+
}): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Desktop tool response interface
|
|
73
|
+
* This is what the Electron app returns after executing the action
|
|
74
|
+
*/
|
|
75
|
+
export interface DesktopToolResponse {
|
|
76
|
+
requiresDesktopExecution: true;
|
|
77
|
+
action: string;
|
|
78
|
+
args: Record<string, unknown>;
|
|
79
|
+
toolCallId?: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Options for creating desktop tools
|
|
83
|
+
*/
|
|
84
|
+
export interface CreateDesktopToolsOptions {
|
|
85
|
+
/**
|
|
86
|
+
* Optional callback that waits for desktop action results.
|
|
87
|
+
* When provided, tools will await this callback to get actual results from the Electron app.
|
|
88
|
+
* When not provided, tools return markers immediately (for non-server contexts).
|
|
89
|
+
*/
|
|
90
|
+
waitForResult?: DesktopToolCallback;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create desktop automation tools for the agent
|
|
94
|
+
* These tools allow AI to control the user's desktop when Ranger Desktop is running
|
|
95
|
+
*/
|
|
96
|
+
export declare function createDesktopTools(options?: CreateDesktopToolsOptions): DynamicStructuredTool[];
|
|
97
|
+
/**
|
|
98
|
+
* Get all desktop tool names
|
|
99
|
+
*/
|
|
100
|
+
export declare function getDesktopToolNames(): DesktopToolName[];
|
|
101
|
+
/**
|
|
102
|
+
* Check if a tool name is a desktop tool
|
|
103
|
+
*/
|
|
104
|
+
export declare function isDesktopTool(name: string): name is DesktopToolName;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './graphs';
|
|
|
12
12
|
export * from './tools/Calculator';
|
|
13
13
|
export * from './tools/CodeExecutor';
|
|
14
14
|
export * from './tools/BrowserTools';
|
|
15
|
+
export * from './tools/DesktopTools';
|
|
15
16
|
export * from './tools/ProgrammaticToolCalling';
|
|
16
17
|
export * from './tools/ToolSearch';
|
|
17
18
|
export * from './tools/handlers';
|
package/src/stream.ts
CHANGED
|
@@ -737,6 +737,23 @@ export function createContentAggregator(): t.ContentAggregatorResult {
|
|
|
737
737
|
};
|
|
738
738
|
|
|
739
739
|
updateContent(runStep.index, contentPart, true);
|
|
740
|
+
} else if (event === GraphEvents.ON_STRUCTURED_OUTPUT) {
|
|
741
|
+
// Handle structured output as text content with formatted JSON
|
|
742
|
+
const structuredData = data as unknown as {
|
|
743
|
+
structuredResponse: Record<string, unknown>;
|
|
744
|
+
schema: Record<string, unknown>;
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
if (structuredData.structuredResponse) {
|
|
748
|
+
const jsonText = JSON.stringify(structuredData.structuredResponse, null, 2);
|
|
749
|
+
const contentPart: t.MessageContentComplex = {
|
|
750
|
+
type: ContentTypes.TEXT,
|
|
751
|
+
text: jsonText,
|
|
752
|
+
};
|
|
753
|
+
// Add at index 0 or next available
|
|
754
|
+
const nextIndex = contentParts.length;
|
|
755
|
+
updateContent(nextIndex, contentPart);
|
|
756
|
+
}
|
|
740
757
|
}
|
|
741
758
|
};
|
|
742
759
|
|
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { tool, DynamicStructuredTool } from '@langchain/core/tools';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type for tool configuration passed by LangChain runtime
|
|
6
|
+
*/
|
|
7
|
+
type ToolCallConfig = { toolCall?: { id?: string } };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Desktop tool names - keep in sync with Ranger Desktop Electron app
|
|
11
|
+
* These tools execute locally in the Electron app, NOT on the server
|
|
12
|
+
*/
|
|
13
|
+
export const EDesktopTools = {
|
|
14
|
+
SCREENSHOT: 'computer_screenshot',
|
|
15
|
+
CLICK: 'computer_click',
|
|
16
|
+
DOUBLE_CLICK: 'computer_double_click',
|
|
17
|
+
RIGHT_CLICK: 'computer_right_click',
|
|
18
|
+
TYPE: 'computer_type',
|
|
19
|
+
KEY: 'computer_key',
|
|
20
|
+
KEY_COMBO: 'computer_key_combo',
|
|
21
|
+
SCROLL: 'computer_scroll',
|
|
22
|
+
DRAG: 'computer_drag',
|
|
23
|
+
GET_ACTIVE_WINDOW: 'computer_get_active_window',
|
|
24
|
+
GET_MOUSE_POSITION: 'computer_get_mouse_position',
|
|
25
|
+
CLIPBOARD_READ: 'clipboard_read',
|
|
26
|
+
CLIPBOARD_WRITE: 'clipboard_write',
|
|
27
|
+
CLIPBOARD_PASTE: 'clipboard_paste',
|
|
28
|
+
WAIT: 'computer_wait',
|
|
29
|
+
} as const;
|
|
30
|
+
|
|
31
|
+
export type DesktopToolName =
|
|
32
|
+
(typeof EDesktopTools)[keyof typeof EDesktopTools];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Callback function type for waiting on desktop action results
|
|
36
|
+
* This allows the server (Ranger) to provide a callback that waits for the Electron app
|
|
37
|
+
* to POST results back to the server before returning to the LLM.
|
|
38
|
+
*
|
|
39
|
+
* @param action - The desktop action (click, type, screenshot, etc.)
|
|
40
|
+
* @param args - Arguments for the action
|
|
41
|
+
* @param toolCallId - Unique ID for this tool call (from config.toolCall.id)
|
|
42
|
+
* @returns Promise that resolves with the actual desktop result
|
|
43
|
+
*/
|
|
44
|
+
export type DesktopToolCallback = (
|
|
45
|
+
action: string,
|
|
46
|
+
args: Record<string, unknown>,
|
|
47
|
+
toolCallId: string
|
|
48
|
+
) => Promise<DesktopActionResult>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Result returned from desktop action execution
|
|
52
|
+
*/
|
|
53
|
+
export interface DesktopActionResult {
|
|
54
|
+
success: boolean;
|
|
55
|
+
error?: string;
|
|
56
|
+
screenshot?: {
|
|
57
|
+
base64: string;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
};
|
|
61
|
+
activeWindow?: {
|
|
62
|
+
title: string;
|
|
63
|
+
app: string;
|
|
64
|
+
bounds?: { x: number; y: number; width: number; height: number };
|
|
65
|
+
};
|
|
66
|
+
mousePosition?: { x: number; y: number };
|
|
67
|
+
clipboard?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if desktop capability is available based on request headers or context
|
|
72
|
+
* The Ranger Desktop Electron app sets these headers when connected:
|
|
73
|
+
* - X-Ranger-Desktop: true
|
|
74
|
+
* - X-Ranger-Desktop-Capable: true
|
|
75
|
+
*/
|
|
76
|
+
export function hasDesktopCapability(req?: {
|
|
77
|
+
headers?: Record<string, string | string[] | undefined>;
|
|
78
|
+
}): boolean {
|
|
79
|
+
if (!req?.headers) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const desktopApp = req.headers['x-ranger-desktop'];
|
|
84
|
+
const desktopCapable = req.headers['x-ranger-desktop-capable'];
|
|
85
|
+
|
|
86
|
+
return desktopApp === 'true' || desktopCapable === 'true';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Tool schemas
|
|
90
|
+
const ScreenshotSchema = z.object({});
|
|
91
|
+
|
|
92
|
+
const ClickSchema = z.object({
|
|
93
|
+
x: z.number().describe('X coordinate to click'),
|
|
94
|
+
y: z.number().describe('Y coordinate to click'),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const DoubleClickSchema = z.object({
|
|
98
|
+
x: z.number().describe('X coordinate to double-click'),
|
|
99
|
+
y: z.number().describe('Y coordinate to double-click'),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const RightClickSchema = z.object({
|
|
103
|
+
x: z.number().describe('X coordinate to right-click'),
|
|
104
|
+
y: z.number().describe('Y coordinate to right-click'),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const TypeSchema = z.object({
|
|
108
|
+
text: z.string().describe('Text to type'),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const KeySchema = z.object({
|
|
112
|
+
key: z
|
|
113
|
+
.string()
|
|
114
|
+
.describe(
|
|
115
|
+
'Key to press (e.g., "Enter", "Tab", "Escape", "Backspace", "Delete", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown", "F1"-"F12")'
|
|
116
|
+
),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const KeyComboSchema = z.object({
|
|
120
|
+
keys: z
|
|
121
|
+
.array(z.string())
|
|
122
|
+
.describe(
|
|
123
|
+
'Array of keys to press together (e.g., ["Control", "c"] for copy, ["Alt", "Tab"] for window switch)'
|
|
124
|
+
),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const ScrollSchema = z.object({
|
|
128
|
+
x: z.number().describe('X coordinate to scroll at'),
|
|
129
|
+
y: z.number().describe('Y coordinate to scroll at'),
|
|
130
|
+
deltaX: z.number().optional().describe('Horizontal scroll amount (pixels)'),
|
|
131
|
+
deltaY: z.number().describe('Vertical scroll amount (pixels, negative = up, positive = down)'),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const DragSchema = z.object({
|
|
135
|
+
startX: z.number().describe('Starting X coordinate'),
|
|
136
|
+
startY: z.number().describe('Starting Y coordinate'),
|
|
137
|
+
endX: z.number().describe('Ending X coordinate'),
|
|
138
|
+
endY: z.number().describe('Ending Y coordinate'),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const GetActiveWindowSchema = z.object({});
|
|
142
|
+
|
|
143
|
+
const GetMousePositionSchema = z.object({});
|
|
144
|
+
|
|
145
|
+
const ClipboardReadSchema = z.object({});
|
|
146
|
+
|
|
147
|
+
const ClipboardWriteSchema = z.object({
|
|
148
|
+
text: z.string().describe('Text to write to clipboard'),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const ClipboardPasteSchema = z.object({});
|
|
152
|
+
|
|
153
|
+
const WaitSchema = z.object({
|
|
154
|
+
ms: z.number().describe('Milliseconds to wait'),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Desktop tool response interface
|
|
159
|
+
* This is what the Electron app returns after executing the action
|
|
160
|
+
*/
|
|
161
|
+
export interface DesktopToolResponse {
|
|
162
|
+
requiresDesktopExecution: true;
|
|
163
|
+
action: string;
|
|
164
|
+
args: Record<string, unknown>;
|
|
165
|
+
toolCallId?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Options for creating desktop tools
|
|
170
|
+
*/
|
|
171
|
+
export interface CreateDesktopToolsOptions {
|
|
172
|
+
/**
|
|
173
|
+
* Optional callback that waits for desktop action results.
|
|
174
|
+
* When provided, tools will await this callback to get actual results from the Electron app.
|
|
175
|
+
* When not provided, tools return markers immediately (for non-server contexts).
|
|
176
|
+
*/
|
|
177
|
+
waitForResult?: DesktopToolCallback;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Format desktop action result for LLM consumption
|
|
182
|
+
*/
|
|
183
|
+
function formatResultForLLM(
|
|
184
|
+
result: DesktopActionResult,
|
|
185
|
+
action: string
|
|
186
|
+
): string {
|
|
187
|
+
if (!result.success && result.error) {
|
|
188
|
+
return `Desktop action "${action}" failed: ${result.error}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const parts: string[] = [];
|
|
192
|
+
|
|
193
|
+
if (result.screenshot) {
|
|
194
|
+
parts.push(
|
|
195
|
+
`Screenshot captured (${result.screenshot.width}x${result.screenshot.height})`
|
|
196
|
+
);
|
|
197
|
+
// The base64 image will be handled separately by the message formatter
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (result.activeWindow) {
|
|
201
|
+
parts.push(`**Active Window:**`);
|
|
202
|
+
parts.push(` - Title: ${result.activeWindow.title}`);
|
|
203
|
+
parts.push(` - App: ${result.activeWindow.app}`);
|
|
204
|
+
if (result.activeWindow.bounds) {
|
|
205
|
+
const b = result.activeWindow.bounds;
|
|
206
|
+
parts.push(` - Position: (${b.x}, ${b.y})`);
|
|
207
|
+
parts.push(` - Size: ${b.width}x${b.height}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (result.mousePosition) {
|
|
212
|
+
parts.push(
|
|
213
|
+
`**Mouse Position:** (${result.mousePosition.x}, ${result.mousePosition.y})`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (result.clipboard !== undefined) {
|
|
218
|
+
parts.push(`**Clipboard Content:** ${result.clipboard}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (parts.length === 0) {
|
|
222
|
+
parts.push(`Desktop action "${action}" completed successfully.`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return parts.join('\n');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Create a tool result (either wait for callback or return marker)
|
|
230
|
+
*/
|
|
231
|
+
async function createToolResult(
|
|
232
|
+
action: string,
|
|
233
|
+
args: Record<string, unknown>,
|
|
234
|
+
config: ToolCallConfig | undefined,
|
|
235
|
+
waitForResult?: DesktopToolCallback
|
|
236
|
+
): Promise<string> {
|
|
237
|
+
const toolCallId = config?.toolCall?.id || `desktop-${Date.now()}`;
|
|
238
|
+
|
|
239
|
+
if (waitForResult) {
|
|
240
|
+
// Server context: wait for actual result from Electron app
|
|
241
|
+
try {
|
|
242
|
+
const result = await waitForResult(action, args, toolCallId);
|
|
243
|
+
return formatResultForLLM(result, action);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const errorMessage =
|
|
246
|
+
error instanceof Error ? error.message : String(error);
|
|
247
|
+
return `Desktop action "${action}" failed: ${errorMessage}`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Non-server context: return marker for later processing
|
|
252
|
+
const response: DesktopToolResponse = {
|
|
253
|
+
requiresDesktopExecution: true,
|
|
254
|
+
action,
|
|
255
|
+
args,
|
|
256
|
+
toolCallId,
|
|
257
|
+
};
|
|
258
|
+
return JSON.stringify(response);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Create desktop automation tools for the agent
|
|
263
|
+
* These tools allow AI to control the user's desktop when Ranger Desktop is running
|
|
264
|
+
*/
|
|
265
|
+
export function createDesktopTools(
|
|
266
|
+
options: CreateDesktopToolsOptions = {}
|
|
267
|
+
): DynamicStructuredTool[] {
|
|
268
|
+
const { waitForResult } = options;
|
|
269
|
+
|
|
270
|
+
return [
|
|
271
|
+
// computer_screenshot
|
|
272
|
+
tool(
|
|
273
|
+
async (_args, config) => {
|
|
274
|
+
return createToolResult(
|
|
275
|
+
EDesktopTools.SCREENSHOT,
|
|
276
|
+
{},
|
|
277
|
+
config as ToolCallConfig,
|
|
278
|
+
waitForResult
|
|
279
|
+
);
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: EDesktopTools.SCREENSHOT,
|
|
283
|
+
description:
|
|
284
|
+
'Take a screenshot of the entire screen. Use this to see what is currently displayed on the desktop.',
|
|
285
|
+
schema: ScreenshotSchema,
|
|
286
|
+
}
|
|
287
|
+
),
|
|
288
|
+
|
|
289
|
+
// computer_click
|
|
290
|
+
tool(
|
|
291
|
+
async (args, config) => {
|
|
292
|
+
return createToolResult(
|
|
293
|
+
EDesktopTools.CLICK,
|
|
294
|
+
args,
|
|
295
|
+
config as ToolCallConfig,
|
|
296
|
+
waitForResult
|
|
297
|
+
);
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: EDesktopTools.CLICK,
|
|
301
|
+
description:
|
|
302
|
+
'Click the mouse at the specified screen coordinates. Use screenshot first to identify the target location.',
|
|
303
|
+
schema: ClickSchema,
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
|
|
307
|
+
// computer_double_click
|
|
308
|
+
tool(
|
|
309
|
+
async (args, config) => {
|
|
310
|
+
return createToolResult(
|
|
311
|
+
EDesktopTools.DOUBLE_CLICK,
|
|
312
|
+
args,
|
|
313
|
+
config as ToolCallConfig,
|
|
314
|
+
waitForResult
|
|
315
|
+
);
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: EDesktopTools.DOUBLE_CLICK,
|
|
319
|
+
description:
|
|
320
|
+
'Double-click the mouse at the specified screen coordinates.',
|
|
321
|
+
schema: DoubleClickSchema,
|
|
322
|
+
}
|
|
323
|
+
),
|
|
324
|
+
|
|
325
|
+
// computer_right_click
|
|
326
|
+
tool(
|
|
327
|
+
async (args, config) => {
|
|
328
|
+
return createToolResult(
|
|
329
|
+
EDesktopTools.RIGHT_CLICK,
|
|
330
|
+
args,
|
|
331
|
+
config as ToolCallConfig,
|
|
332
|
+
waitForResult
|
|
333
|
+
);
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: EDesktopTools.RIGHT_CLICK,
|
|
337
|
+
description:
|
|
338
|
+
'Right-click the mouse at the specified screen coordinates to open context menus.',
|
|
339
|
+
schema: RightClickSchema,
|
|
340
|
+
}
|
|
341
|
+
),
|
|
342
|
+
|
|
343
|
+
// computer_type
|
|
344
|
+
tool(
|
|
345
|
+
async (args, config) => {
|
|
346
|
+
return createToolResult(
|
|
347
|
+
EDesktopTools.TYPE,
|
|
348
|
+
args,
|
|
349
|
+
config as ToolCallConfig,
|
|
350
|
+
waitForResult
|
|
351
|
+
);
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
name: EDesktopTools.TYPE,
|
|
355
|
+
description:
|
|
356
|
+
'Type text using the keyboard. Make sure the target input field is focused first (use click).',
|
|
357
|
+
schema: TypeSchema,
|
|
358
|
+
}
|
|
359
|
+
),
|
|
360
|
+
|
|
361
|
+
// computer_key
|
|
362
|
+
tool(
|
|
363
|
+
async (args, config) => {
|
|
364
|
+
return createToolResult(
|
|
365
|
+
EDesktopTools.KEY,
|
|
366
|
+
args,
|
|
367
|
+
config as ToolCallConfig,
|
|
368
|
+
waitForResult
|
|
369
|
+
);
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
name: EDesktopTools.KEY,
|
|
373
|
+
description:
|
|
374
|
+
'Press a single key on the keyboard (Enter, Tab, Escape, arrow keys, function keys, etc.).',
|
|
375
|
+
schema: KeySchema,
|
|
376
|
+
}
|
|
377
|
+
),
|
|
378
|
+
|
|
379
|
+
// computer_key_combo
|
|
380
|
+
tool(
|
|
381
|
+
async (args, config) => {
|
|
382
|
+
return createToolResult(
|
|
383
|
+
EDesktopTools.KEY_COMBO,
|
|
384
|
+
args,
|
|
385
|
+
config as ToolCallConfig,
|
|
386
|
+
waitForResult
|
|
387
|
+
);
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
name: EDesktopTools.KEY_COMBO,
|
|
391
|
+
description:
|
|
392
|
+
'Press a key combination (e.g., Ctrl+C to copy, Ctrl+V to paste, Alt+Tab to switch windows).',
|
|
393
|
+
schema: KeyComboSchema,
|
|
394
|
+
}
|
|
395
|
+
),
|
|
396
|
+
|
|
397
|
+
// computer_scroll
|
|
398
|
+
tool(
|
|
399
|
+
async (args, config) => {
|
|
400
|
+
return createToolResult(
|
|
401
|
+
EDesktopTools.SCROLL,
|
|
402
|
+
args,
|
|
403
|
+
config as ToolCallConfig,
|
|
404
|
+
waitForResult
|
|
405
|
+
);
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
name: EDesktopTools.SCROLL,
|
|
409
|
+
description:
|
|
410
|
+
'Scroll at the specified screen coordinates. Use negative deltaY to scroll up, positive to scroll down.',
|
|
411
|
+
schema: ScrollSchema,
|
|
412
|
+
}
|
|
413
|
+
),
|
|
414
|
+
|
|
415
|
+
// computer_drag
|
|
416
|
+
tool(
|
|
417
|
+
async (args, config) => {
|
|
418
|
+
return createToolResult(
|
|
419
|
+
EDesktopTools.DRAG,
|
|
420
|
+
args,
|
|
421
|
+
config as ToolCallConfig,
|
|
422
|
+
waitForResult
|
|
423
|
+
);
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: EDesktopTools.DRAG,
|
|
427
|
+
description:
|
|
428
|
+
'Drag the mouse from one position to another (for moving windows, selecting text, etc.).',
|
|
429
|
+
schema: DragSchema,
|
|
430
|
+
}
|
|
431
|
+
),
|
|
432
|
+
|
|
433
|
+
// computer_get_active_window
|
|
434
|
+
tool(
|
|
435
|
+
async (_args, config) => {
|
|
436
|
+
return createToolResult(
|
|
437
|
+
EDesktopTools.GET_ACTIVE_WINDOW,
|
|
438
|
+
{},
|
|
439
|
+
config as ToolCallConfig,
|
|
440
|
+
waitForResult
|
|
441
|
+
);
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
name: EDesktopTools.GET_ACTIVE_WINDOW,
|
|
445
|
+
description:
|
|
446
|
+
'Get information about the currently active window (title, application name, position, size).',
|
|
447
|
+
schema: GetActiveWindowSchema,
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
|
|
451
|
+
// computer_get_mouse_position
|
|
452
|
+
tool(
|
|
453
|
+
async (_args, config) => {
|
|
454
|
+
return createToolResult(
|
|
455
|
+
EDesktopTools.GET_MOUSE_POSITION,
|
|
456
|
+
{},
|
|
457
|
+
config as ToolCallConfig,
|
|
458
|
+
waitForResult
|
|
459
|
+
);
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
name: EDesktopTools.GET_MOUSE_POSITION,
|
|
463
|
+
description: 'Get the current mouse cursor position on screen.',
|
|
464
|
+
schema: GetMousePositionSchema,
|
|
465
|
+
}
|
|
466
|
+
),
|
|
467
|
+
|
|
468
|
+
// clipboard_read
|
|
469
|
+
tool(
|
|
470
|
+
async (_args, config) => {
|
|
471
|
+
return createToolResult(
|
|
472
|
+
EDesktopTools.CLIPBOARD_READ,
|
|
473
|
+
{},
|
|
474
|
+
config as ToolCallConfig,
|
|
475
|
+
waitForResult
|
|
476
|
+
);
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
name: EDesktopTools.CLIPBOARD_READ,
|
|
480
|
+
description: 'Read the current contents of the system clipboard.',
|
|
481
|
+
schema: ClipboardReadSchema,
|
|
482
|
+
}
|
|
483
|
+
),
|
|
484
|
+
|
|
485
|
+
// clipboard_write
|
|
486
|
+
tool(
|
|
487
|
+
async (args, config) => {
|
|
488
|
+
return createToolResult(
|
|
489
|
+
EDesktopTools.CLIPBOARD_WRITE,
|
|
490
|
+
args,
|
|
491
|
+
config as ToolCallConfig,
|
|
492
|
+
waitForResult
|
|
493
|
+
);
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: EDesktopTools.CLIPBOARD_WRITE,
|
|
497
|
+
description: 'Write text to the system clipboard.',
|
|
498
|
+
schema: ClipboardWriteSchema,
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
|
|
502
|
+
// clipboard_paste
|
|
503
|
+
tool(
|
|
504
|
+
async (_args, config) => {
|
|
505
|
+
return createToolResult(
|
|
506
|
+
EDesktopTools.CLIPBOARD_PASTE,
|
|
507
|
+
{},
|
|
508
|
+
config as ToolCallConfig,
|
|
509
|
+
waitForResult
|
|
510
|
+
);
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
name: EDesktopTools.CLIPBOARD_PASTE,
|
|
514
|
+
description:
|
|
515
|
+
'Paste the clipboard contents (equivalent to Ctrl+V). Use clipboard_write first to set the content.',
|
|
516
|
+
schema: ClipboardPasteSchema,
|
|
517
|
+
}
|
|
518
|
+
),
|
|
519
|
+
|
|
520
|
+
// computer_wait
|
|
521
|
+
tool(
|
|
522
|
+
async (args, config) => {
|
|
523
|
+
return createToolResult(
|
|
524
|
+
EDesktopTools.WAIT,
|
|
525
|
+
args,
|
|
526
|
+
config as ToolCallConfig,
|
|
527
|
+
waitForResult
|
|
528
|
+
);
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: EDesktopTools.WAIT,
|
|
532
|
+
description:
|
|
533
|
+
'Wait for the specified number of milliseconds. Use this to wait for UI animations or loading.',
|
|
534
|
+
schema: WaitSchema,
|
|
535
|
+
}
|
|
536
|
+
),
|
|
537
|
+
];
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Get all desktop tool names
|
|
542
|
+
*/
|
|
543
|
+
export function getDesktopToolNames(): DesktopToolName[] {
|
|
544
|
+
return Object.values(EDesktopTools);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Check if a tool name is a desktop tool
|
|
549
|
+
*/
|
|
550
|
+
export function isDesktopTool(name: string): name is DesktopToolName {
|
|
551
|
+
return Object.values(EDesktopTools).includes(name as DesktopToolName);
|
|
552
|
+
}
|