junis 0.3.17 → 0.4.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/dist/cli/index.js +39 -19
- package/dist/server/mcp.js +39 -19
- package/dist/server/stdio.js +3 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -570,6 +570,9 @@ var FilesystemTools = class {
|
|
|
570
570
|
"- For reading files prefer read_file, for editing prefer edit_block, for searching prefer search_code.",
|
|
571
571
|
"- NOT for macOS app GUI interaction. Use desktop_* tools instead: desktop_open_app, desktop_see, desktop_click, desktop_type, desktop_paste, desktop_hotkey, desktop_scroll, desktop_move, desktop_menu, desktop_screenshot.",
|
|
572
572
|
"- Exception: permission fix commands (swift -e, peekaboo permissions, open 'x-apple.systempreferences:...').",
|
|
573
|
+
"- Exception: osascript coordinate queries \u2014 Use osascript via this tool to query exact UI element position and size before any click/move/drag operation.",
|
|
574
|
+
" Pattern: osascript + System Events \u2192 position + size \u2192 center = (x + w/2, y + h/2) \u2192 desktop_click(coords).",
|
|
575
|
+
" This is the ONLY reliable way to get pixel-accurate coordinates on macOS. NEVER estimate coords from screenshots.",
|
|
573
576
|
"",
|
|
574
577
|
"BEHAVIOR:",
|
|
575
578
|
"- Execute commands directly when the user requests them. Do not ask for confirmation \u2014 the user has already decided.",
|
|
@@ -2101,19 +2104,8 @@ function checkBlacklist(app) {
|
|
|
2101
2104
|
function json(data) {
|
|
2102
2105
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
2103
2106
|
}
|
|
2104
|
-
async function
|
|
2105
|
-
|
|
2106
|
-
try {
|
|
2107
|
-
const { stdout } = await execa("osascript", [
|
|
2108
|
-
"-e",
|
|
2109
|
-
'tell application "System Events" to get name of first application process whose frontmost is true'
|
|
2110
|
-
]);
|
|
2111
|
-
app = stdout.trim();
|
|
2112
|
-
} catch {
|
|
2113
|
-
return null;
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
const safeApp = app.replace(/[\\"]/g, "\\$&");
|
|
2107
|
+
async function searchProcessElements(processName, query) {
|
|
2108
|
+
const safeApp = processName.replace(/[\\"]/g, "\\$&");
|
|
2117
2109
|
const safeQuery = query.replace(/[\\"]/g, "\\$&");
|
|
2118
2110
|
const script = `
|
|
2119
2111
|
tell application "System Events"
|
|
@@ -2158,6 +2150,26 @@ return "NOT_FOUND"
|
|
|
2158
2150
|
return null;
|
|
2159
2151
|
}
|
|
2160
2152
|
}
|
|
2153
|
+
async function resolveElementCoords(query, app) {
|
|
2154
|
+
let targetApp = app;
|
|
2155
|
+
if (!targetApp) {
|
|
2156
|
+
try {
|
|
2157
|
+
const { stdout } = await execa("osascript", [
|
|
2158
|
+
"-e",
|
|
2159
|
+
'tell application "System Events" to get name of first application process whose frontmost is true'
|
|
2160
|
+
]);
|
|
2161
|
+
targetApp = stdout.trim();
|
|
2162
|
+
} catch {
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
const result = await searchProcessElements(targetApp, query);
|
|
2167
|
+
if (result) return result;
|
|
2168
|
+
if (targetApp !== "Dock") {
|
|
2169
|
+
return await searchProcessElements("Dock", query);
|
|
2170
|
+
}
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2161
2173
|
var DesktopTools = class {
|
|
2162
2174
|
register(server) {
|
|
2163
2175
|
server.tool(
|
|
@@ -2197,8 +2209,9 @@ var DesktopTools = class {
|
|
|
2197
2209
|
"desktop_screenshot",
|
|
2198
2210
|
[
|
|
2199
2211
|
"Take a screenshot. Returns base64 image at logical resolution (matches click coordinate system 1:1).",
|
|
2200
|
-
"Use for visual context or to verify UI state
|
|
2201
|
-
"
|
|
2212
|
+
"Use for visual context or to verify UI state ONLY.",
|
|
2213
|
+
"WARNING: NEVER estimate click coordinates from screenshot images \u2014 visual estimation causes misclicks. Use desktop_click(query, app) for auto-resolution, or execute_command + osascript for exact coords.",
|
|
2214
|
+
"Do not use visual coordinates from this screenshot directly. Use execute_command + osascript to verify exact element position first."
|
|
2202
2215
|
].join("\n"),
|
|
2203
2216
|
{
|
|
2204
2217
|
app: z5.string().optional().describe("Capture specific app window"),
|
|
@@ -2237,9 +2250,10 @@ var DesktopTools = class {
|
|
|
2237
2250
|
[
|
|
2238
2251
|
"Click a UI element by text label (query), coordinates (coords), or element ID (on).",
|
|
2239
2252
|
"BEST: Use query with app name \u2014 auto-resolves to exact screen coords via accessibility API. No desktop_see needed.",
|
|
2240
|
-
"GOOD: Use coords 'x,y' from
|
|
2253
|
+
"GOOD: Use coords 'x,y' \u2014 MUST be from osascript position+size center calculation, NEVER from visual screenshot estimation.",
|
|
2254
|
+
"Before using coords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots.",
|
|
2241
2255
|
"CAUTION: 'on' (element ID) has known offset bug \u2014 use coords or query instead when possible.",
|
|
2242
|
-
"If not found
|
|
2256
|
+
"If query not found: use execute_command + osascript to get element position+size, then center = (x + w/2, y + h/2). Or try desktop_menu, desktop_hotkey.",
|
|
2243
2257
|
"NOTE: Web page elements (inside browser) are invisible to desktop tools. Use browser_* tools instead."
|
|
2244
2258
|
].join("\n"),
|
|
2245
2259
|
{
|
|
@@ -2305,6 +2319,7 @@ var DesktopTools = class {
|
|
|
2305
2319
|
"desktop_paste",
|
|
2306
2320
|
[
|
|
2307
2321
|
"Paste via clipboard (Cmd+V). Atomic: saves clipboard \u2192 sets content \u2192 pastes \u2192 restores.",
|
|
2322
|
+
"IMPORTANT: Focus the target field first (click it with desktop_click) before pasting.",
|
|
2308
2323
|
"Supports all Unicode (Korean, Japanese, Chinese, emoji). Use instead of desktop_type for non-ASCII.",
|
|
2309
2324
|
"Can also paste file contents via filePath."
|
|
2310
2325
|
].join("\n"),
|
|
@@ -2387,7 +2402,10 @@ var DesktopTools = class {
|
|
|
2387
2402
|
);
|
|
2388
2403
|
server.tool(
|
|
2389
2404
|
"desktop_move",
|
|
2390
|
-
|
|
2405
|
+
[
|
|
2406
|
+
"Move mouse cursor without clicking. Use before scroll or to hover.",
|
|
2407
|
+
"Before using coords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots."
|
|
2408
|
+
].join("\n"),
|
|
2391
2409
|
{
|
|
2392
2410
|
coords: z5.string().optional().describe("Screen coordinates 'x,y'"),
|
|
2393
2411
|
to: z5.string().optional().describe("Element text/label to move to"),
|
|
@@ -2422,7 +2440,8 @@ var DesktopTools = class {
|
|
|
2422
2440
|
"desktop_drag",
|
|
2423
2441
|
[
|
|
2424
2442
|
"Drag and drop between elements or coordinates. Supports cross-app drag (e.g. file to Trash).",
|
|
2425
|
-
"
|
|
2443
|
+
"Prefer fromCoords/toCoords for accuracy. Element IDs (from/to) have known offset bug.",
|
|
2444
|
+
"Before using fromCoords/toCoords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots."
|
|
2426
2445
|
].join("\n"),
|
|
2427
2446
|
{
|
|
2428
2447
|
from: z5.string().optional().describe("Source element ID from desktop_see"),
|
|
@@ -2619,6 +2638,7 @@ var DesktopTools = class {
|
|
|
2619
2638
|
app: z5.string().optional().describe("App to open with")
|
|
2620
2639
|
},
|
|
2621
2640
|
async ({ url, app }) => {
|
|
2641
|
+
checkBlacklist(app);
|
|
2622
2642
|
const args = ["open", url];
|
|
2623
2643
|
if (app) args.push("--app", app);
|
|
2624
2644
|
return json(await peekaboo(args));
|
package/dist/server/mcp.js
CHANGED
|
@@ -86,6 +86,9 @@ var FilesystemTools = class {
|
|
|
86
86
|
"- For reading files prefer read_file, for editing prefer edit_block, for searching prefer search_code.",
|
|
87
87
|
"- NOT for macOS app GUI interaction. Use desktop_* tools instead: desktop_open_app, desktop_see, desktop_click, desktop_type, desktop_paste, desktop_hotkey, desktop_scroll, desktop_move, desktop_menu, desktop_screenshot.",
|
|
88
88
|
"- Exception: permission fix commands (swift -e, peekaboo permissions, open 'x-apple.systempreferences:...').",
|
|
89
|
+
"- Exception: osascript coordinate queries \u2014 Use osascript via this tool to query exact UI element position and size before any click/move/drag operation.",
|
|
90
|
+
" Pattern: osascript + System Events \u2192 position + size \u2192 center = (x + w/2, y + h/2) \u2192 desktop_click(coords).",
|
|
91
|
+
" This is the ONLY reliable way to get pixel-accurate coordinates on macOS. NEVER estimate coords from screenshots.",
|
|
89
92
|
"",
|
|
90
93
|
"BEHAVIOR:",
|
|
91
94
|
"- Execute commands directly when the user requests them. Do not ask for confirmation \u2014 the user has already decided.",
|
|
@@ -1617,19 +1620,8 @@ function checkBlacklist(app) {
|
|
|
1617
1620
|
function json(data) {
|
|
1618
1621
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
1619
1622
|
}
|
|
1620
|
-
async function
|
|
1621
|
-
|
|
1622
|
-
try {
|
|
1623
|
-
const { stdout } = await execa("osascript", [
|
|
1624
|
-
"-e",
|
|
1625
|
-
'tell application "System Events" to get name of first application process whose frontmost is true'
|
|
1626
|
-
]);
|
|
1627
|
-
app = stdout.trim();
|
|
1628
|
-
} catch {
|
|
1629
|
-
return null;
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
const safeApp = app.replace(/[\\"]/g, "\\$&");
|
|
1623
|
+
async function searchProcessElements(processName, query) {
|
|
1624
|
+
const safeApp = processName.replace(/[\\"]/g, "\\$&");
|
|
1633
1625
|
const safeQuery = query.replace(/[\\"]/g, "\\$&");
|
|
1634
1626
|
const script = `
|
|
1635
1627
|
tell application "System Events"
|
|
@@ -1674,6 +1666,26 @@ return "NOT_FOUND"
|
|
|
1674
1666
|
return null;
|
|
1675
1667
|
}
|
|
1676
1668
|
}
|
|
1669
|
+
async function resolveElementCoords(query, app) {
|
|
1670
|
+
let targetApp = app;
|
|
1671
|
+
if (!targetApp) {
|
|
1672
|
+
try {
|
|
1673
|
+
const { stdout } = await execa("osascript", [
|
|
1674
|
+
"-e",
|
|
1675
|
+
'tell application "System Events" to get name of first application process whose frontmost is true'
|
|
1676
|
+
]);
|
|
1677
|
+
targetApp = stdout.trim();
|
|
1678
|
+
} catch {
|
|
1679
|
+
return null;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
const result = await searchProcessElements(targetApp, query);
|
|
1683
|
+
if (result) return result;
|
|
1684
|
+
if (targetApp !== "Dock") {
|
|
1685
|
+
return await searchProcessElements("Dock", query);
|
|
1686
|
+
}
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1677
1689
|
var DesktopTools = class {
|
|
1678
1690
|
register(server) {
|
|
1679
1691
|
server.tool(
|
|
@@ -1713,8 +1725,9 @@ var DesktopTools = class {
|
|
|
1713
1725
|
"desktop_screenshot",
|
|
1714
1726
|
[
|
|
1715
1727
|
"Take a screenshot. Returns base64 image at logical resolution (matches click coordinate system 1:1).",
|
|
1716
|
-
"Use for visual context or to verify UI state
|
|
1717
|
-
"
|
|
1728
|
+
"Use for visual context or to verify UI state ONLY.",
|
|
1729
|
+
"WARNING: NEVER estimate click coordinates from screenshot images \u2014 visual estimation causes misclicks. Use desktop_click(query, app) for auto-resolution, or execute_command + osascript for exact coords.",
|
|
1730
|
+
"Do not use visual coordinates from this screenshot directly. Use execute_command + osascript to verify exact element position first."
|
|
1718
1731
|
].join("\n"),
|
|
1719
1732
|
{
|
|
1720
1733
|
app: z5.string().optional().describe("Capture specific app window"),
|
|
@@ -1753,9 +1766,10 @@ var DesktopTools = class {
|
|
|
1753
1766
|
[
|
|
1754
1767
|
"Click a UI element by text label (query), coordinates (coords), or element ID (on).",
|
|
1755
1768
|
"BEST: Use query with app name \u2014 auto-resolves to exact screen coords via accessibility API. No desktop_see needed.",
|
|
1756
|
-
"GOOD: Use coords 'x,y' from
|
|
1769
|
+
"GOOD: Use coords 'x,y' \u2014 MUST be from osascript position+size center calculation, NEVER from visual screenshot estimation.",
|
|
1770
|
+
"Before using coords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots.",
|
|
1757
1771
|
"CAUTION: 'on' (element ID) has known offset bug \u2014 use coords or query instead when possible.",
|
|
1758
|
-
"If not found
|
|
1772
|
+
"If query not found: use execute_command + osascript to get element position+size, then center = (x + w/2, y + h/2). Or try desktop_menu, desktop_hotkey.",
|
|
1759
1773
|
"NOTE: Web page elements (inside browser) are invisible to desktop tools. Use browser_* tools instead."
|
|
1760
1774
|
].join("\n"),
|
|
1761
1775
|
{
|
|
@@ -1821,6 +1835,7 @@ var DesktopTools = class {
|
|
|
1821
1835
|
"desktop_paste",
|
|
1822
1836
|
[
|
|
1823
1837
|
"Paste via clipboard (Cmd+V). Atomic: saves clipboard \u2192 sets content \u2192 pastes \u2192 restores.",
|
|
1838
|
+
"IMPORTANT: Focus the target field first (click it with desktop_click) before pasting.",
|
|
1824
1839
|
"Supports all Unicode (Korean, Japanese, Chinese, emoji). Use instead of desktop_type for non-ASCII.",
|
|
1825
1840
|
"Can also paste file contents via filePath."
|
|
1826
1841
|
].join("\n"),
|
|
@@ -1903,7 +1918,10 @@ var DesktopTools = class {
|
|
|
1903
1918
|
);
|
|
1904
1919
|
server.tool(
|
|
1905
1920
|
"desktop_move",
|
|
1906
|
-
|
|
1921
|
+
[
|
|
1922
|
+
"Move mouse cursor without clicking. Use before scroll or to hover.",
|
|
1923
|
+
"Before using coords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots."
|
|
1924
|
+
].join("\n"),
|
|
1907
1925
|
{
|
|
1908
1926
|
coords: z5.string().optional().describe("Screen coordinates 'x,y'"),
|
|
1909
1927
|
to: z5.string().optional().describe("Element text/label to move to"),
|
|
@@ -1938,7 +1956,8 @@ var DesktopTools = class {
|
|
|
1938
1956
|
"desktop_drag",
|
|
1939
1957
|
[
|
|
1940
1958
|
"Drag and drop between elements or coordinates. Supports cross-app drag (e.g. file to Trash).",
|
|
1941
|
-
"
|
|
1959
|
+
"Prefer fromCoords/toCoords for accuracy. Element IDs (from/to) have known offset bug.",
|
|
1960
|
+
"Before using fromCoords/toCoords, always query exact position via execute_command + osascript. Calculate center = position + size/2. Never estimate from screenshots."
|
|
1942
1961
|
].join("\n"),
|
|
1943
1962
|
{
|
|
1944
1963
|
from: z5.string().optional().describe("Source element ID from desktop_see"),
|
|
@@ -2135,6 +2154,7 @@ var DesktopTools = class {
|
|
|
2135
2154
|
app: z5.string().optional().describe("App to open with")
|
|
2136
2155
|
},
|
|
2137
2156
|
async ({ url, app }) => {
|
|
2157
|
+
checkBlacklist(app);
|
|
2138
2158
|
const args = ["open", url];
|
|
2139
2159
|
if (app) args.push("--app", app);
|
|
2140
2160
|
return json(await peekaboo(args));
|
package/dist/server/stdio.js
CHANGED
|
@@ -87,6 +87,9 @@ var FilesystemTools = class {
|
|
|
87
87
|
"- For reading files prefer read_file, for editing prefer edit_block, for searching prefer search_code.",
|
|
88
88
|
"- NOT for macOS app GUI interaction. Use desktop_* tools instead: desktop_open_app, desktop_see, desktop_click, desktop_type, desktop_paste, desktop_hotkey, desktop_scroll, desktop_move, desktop_menu, desktop_screenshot.",
|
|
89
89
|
"- Exception: permission fix commands (swift -e, peekaboo permissions, open 'x-apple.systempreferences:...').",
|
|
90
|
+
"- Exception: osascript coordinate queries \u2014 Use osascript via this tool to query exact UI element position and size before any click/move/drag operation.",
|
|
91
|
+
" Pattern: osascript + System Events \u2192 position + size \u2192 center = (x + w/2, y + h/2) \u2192 desktop_click(coords).",
|
|
92
|
+
" This is the ONLY reliable way to get pixel-accurate coordinates on macOS. NEVER estimate coords from screenshots.",
|
|
90
93
|
"",
|
|
91
94
|
"BEHAVIOR:",
|
|
92
95
|
"- Execute commands directly when the user requests them. Do not ask for confirmation \u2014 the user has already decided.",
|