@yfwu2020/dsh-selection-explain 0.13.0 → 0.13.1

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 (67) hide show
  1. package/README.md +3 -3
  2. package/lib/client.js +11672 -11473
  3. package/lib/client.js.map +4 -4
  4. package/lib/host/analyze-conclusion.js +115 -0
  5. package/lib/host/analyze-conclusion.js.map +1 -0
  6. package/lib/host/analyze-execution-types.js +2 -0
  7. package/lib/host/analyze-execution-types.js.map +1 -0
  8. package/lib/host/analyze-execution.js +166 -0
  9. package/lib/host/analyze-execution.js.map +1 -0
  10. package/lib/host/analyze-history.js +110 -0
  11. package/lib/host/analyze-history.js.map +1 -0
  12. package/lib/host/analyze-messages.js +95 -0
  13. package/lib/host/analyze-messages.js.map +1 -0
  14. package/lib/host/analyze-output.js +69 -0
  15. package/lib/host/analyze-output.js.map +1 -0
  16. package/lib/host/analyze-prompt.js +110 -0
  17. package/lib/host/analyze-prompt.js.map +1 -0
  18. package/lib/host/analyze-request.js +129 -0
  19. package/lib/host/analyze-request.js.map +1 -0
  20. package/lib/host/analyze-round.js +121 -0
  21. package/lib/host/analyze-round.js.map +1 -0
  22. package/lib/host/analyze-tool-execution.js +98 -0
  23. package/lib/host/analyze-tool-execution.js.map +1 -0
  24. package/lib/host/analyze-tools.js +79 -0
  25. package/lib/host/analyze-tools.js.map +1 -0
  26. package/lib/host/analyze-types.js +2 -0
  27. package/lib/host/analyze-types.js.map +1 -0
  28. package/lib/host/analyze.js +30 -977
  29. package/lib/host/analyze.js.map +1 -1
  30. package/lib/host/native-probe.js +66 -0
  31. package/lib/host/native-probe.js.map +1 -0
  32. package/lib/host/plugin.js +9 -10
  33. package/lib/host/plugin.js.map +1 -1
  34. package/lib/host/shot-capture.js +322 -0
  35. package/lib/host/shot-capture.js.map +1 -0
  36. package/lib/host/shot-geometry.js +183 -0
  37. package/lib/host/shot-geometry.js.map +1 -0
  38. package/lib/host/shot-platform.js +208 -0
  39. package/lib/host/shot-platform.js.map +1 -0
  40. package/lib/host/shot-service.js +127 -0
  41. package/lib/host/shot-service.js.map +1 -0
  42. package/lib/host/shot-types.js +5 -0
  43. package/lib/host/shot-types.js.map +1 -0
  44. package/lib/host/shot.js +117 -949
  45. package/lib/host/shot.js.map +1 -1
  46. package/lib/types/host/analyze-conclusion.d.ts +3 -0
  47. package/lib/types/host/analyze-execution-types.d.ts +54 -0
  48. package/lib/types/host/analyze-execution.d.ts +3 -0
  49. package/lib/types/host/analyze-history.d.ts +41 -0
  50. package/lib/types/host/analyze-messages.d.ts +15 -0
  51. package/lib/types/host/analyze-output.d.ts +8 -0
  52. package/lib/types/host/analyze-prompt.d.ts +15 -0
  53. package/lib/types/host/analyze-request.d.ts +28 -0
  54. package/lib/types/host/analyze-round.d.ts +7 -0
  55. package/lib/types/host/analyze-tool-execution.d.ts +4 -0
  56. package/lib/types/host/analyze-tools.d.ts +15 -0
  57. package/lib/types/host/analyze-types.d.ts +13 -0
  58. package/lib/types/host/analyze.d.ts +4 -4
  59. package/lib/types/host/native-probe.d.ts +10 -0
  60. package/lib/types/host/shot-capture.d.ts +11 -0
  61. package/lib/types/host/shot-geometry.d.ts +37 -0
  62. package/lib/types/host/shot-platform.d.ts +11 -0
  63. package/lib/types/host/shot-service.d.ts +17 -0
  64. package/lib/types/host/shot-types.d.ts +105 -0
  65. package/lib/types/host/shot.d.ts +14 -71
  66. package/native/window-list.c +139 -0
  67. package/package.json +2 -1
@@ -0,0 +1,139 @@
1
+ /*
2
+ * dsh-selection-explain · 窗口列表探针(纯 C + CoreFoundation)
3
+ *
4
+ * 干什么:把"当前屏幕上所有窗口"的名字与矩形打成一个 JSON 数组。
5
+ * 为什么需要它:截图提问要"带出整窗" —— 用户框了一块,我们要知道**那块属于哪个窗口**,
6
+ * 才能把整个窗口截下来(而不是裁一圈边框)。Node 没有 CoreGraphics 绑定,所以编一个小二进制。
7
+ * 与本包 native/mic-probe.c 同一套办法:纯 C、无 ObjC、出错就整体降级。
8
+ *
9
+ * 输出(一行 JSON,数组顺序即前后顺序,前一个更靠前):
10
+ * [{"id":123,"x":0,"y":25,"w":1200,"h":800,"layer":0,"alpha":1.00,"owner":"Code"}, ...]
11
+ *
12
+ * 约定:
13
+ * · 只列 on-screen、非桌面元素的窗口;宽或高 < 8 的丢掉(菜单残片、零尺寸辅助窗口);
14
+ * · layer 0 是普通应用窗口(菜单栏/悬浮窗/状态栏都在别的层);
15
+ * · 坐标是**全局点**(左上角原点 = 主屏左上角),与截图文件里那个矩形同一套坐标系。
16
+ *
17
+ * 另有 `--displays`:打"当前活跃显示器"的矩形(全局点)与像素尺寸。
18
+ * 截图范围是「选区 + 留白」时,用它把外扩矩形裁到选区中心所在的那块屏,
19
+ * 否则 screencapture -R 越界时的裁切原点不可预期(红框会偏)。
20
+ * [{"id":1,"x":0,"y":0,"w":1920,"h":1080,"index":1,"main":1}, ...]
21
+ *
22
+ * `index` 是 `screencapture -D` 的编号(1 = 主显示器),按 CGGetActiveDisplayList
23
+ * 的顺序给;`-D` 是截副屏唯一可靠的办法(`-R` 不接受负坐标)。
24
+ * 截图的实际像素尺寸以 `screencapture` 输出为准,不再从这里报(不同缩放下
25
+ * CGDisplayPixelsWide 与截图像素并不等价)。
26
+ */
27
+ #include <CoreGraphics/CoreGraphics.h>
28
+ #include <CoreFoundation/CoreFoundation.h>
29
+ #include <stdio.h>
30
+ #include <string.h>
31
+
32
+ /** JSON 字符串转义:owner 里可能出现引号/反斜杠(罕见,但别拼坏 JSON)。 */
33
+ static void jsonEscape(const char *src, char *dst, size_t n) {
34
+ size_t j = 0;
35
+ for (size_t i = 0; src && src[i] && j + 2 < n; i++) {
36
+ unsigned char c = (unsigned char)src[i];
37
+ if (c == '"' || c == '\\') {
38
+ dst[j++] = '\\';
39
+ dst[j++] = (char)c;
40
+ } else if (c < 0x20) {
41
+ dst[j++] = ' ';
42
+ } else {
43
+ dst[j++] = (char)c;
44
+ }
45
+ }
46
+ dst[j] = '\0';
47
+ }
48
+
49
+ /** CFNumber → double,失败给 fallback。 */
50
+ static double numOr(CFDictionaryRef dict, CFStringRef key, double fallback) {
51
+ CFTypeRef v = CFDictionaryGetValue(dict, key);
52
+ double out = fallback;
53
+ if (v && CFGetTypeID(v) == CFNumberGetTypeID()) {
54
+ if (!CFNumberGetValue((CFNumberRef)v, kCFNumberDoubleType, &out)) out = fallback;
55
+ }
56
+ return out;
57
+ }
58
+
59
+ /**
60
+ * `--displays`:活跃显示器的全局矩形(点)与像素尺寸。
61
+ *
62
+ * 坐标与 CGWindowList 的窗口矩形、截图的 xattr 矩形是同一套全局点坐标系;
63
+ * 副屏在主屏左边时 x 会是负数,调用方必须按**全局点**处理。
64
+ */
65
+ static void printDisplays(void) {
66
+ CGDirectDisplayID ids[32];
67
+ uint32_t count = 0;
68
+ CGError err = CGGetActiveDisplayList(32, ids, &count);
69
+ /* 锁屏 / 显示器睡眠时 active 可能为空:退到 online,再退到主屏,不能因此让截图整体不可用 */
70
+ if (err != kCGErrorSuccess || count == 0) {
71
+ err = CGGetOnlineDisplayList(32, ids, &count);
72
+ }
73
+ if (err != kCGErrorSuccess || count == 0) {
74
+ ids[0] = CGMainDisplayID();
75
+ count = 1;
76
+ }
77
+ printf("[");
78
+ uint32_t emitted = 0;
79
+ for (uint32_t i = 0; i < count; i++) {
80
+ CGRect b = CGDisplayBounds(ids[i]);
81
+ if (b.size.width < 1 || b.size.height < 1) continue;
82
+ if (emitted > 0) printf(",");
83
+ printf("{\"id\":%u,\"x\":%.1f,\"y\":%.1f,\"w\":%.1f,\"h\":%.1f,\"index\":%u,\"main\":%d}",
84
+ (unsigned)ids[i], b.origin.x, b.origin.y, b.size.width, b.size.height,
85
+ emitted + 1, CGDisplayIsMain(ids[i]) ? 1 : 0);
86
+ emitted++;
87
+ }
88
+ printf("]\n");
89
+ }
90
+
91
+ int main(int argc, char **argv) {
92
+ if (argc > 1 && strcmp(argv[1], "--displays") == 0) {
93
+ printDisplays();
94
+ return 0;
95
+ }
96
+ CFArrayRef wins = CGWindowListCopyWindowInfo(
97
+ kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
98
+ long n = wins ? CFArrayGetCount(wins) : 0;
99
+ printf("[");
100
+ int first = 1;
101
+ for (long i = 0; i < n; i++) {
102
+ CFDictionaryRef w = (CFDictionaryRef)CFArrayGetValueAtIndex(wins, i);
103
+ if (!w || CFGetTypeID(w) != CFDictionaryGetTypeID()) continue;
104
+
105
+ CFTypeRef idRef = CFDictionaryGetValue(w, kCGWindowNumber);
106
+ if (!idRef || CFGetTypeID(idRef) != CFNumberGetTypeID()) continue;
107
+ int wid = 0;
108
+ if (!CFNumberGetValue((CFNumberRef)idRef, kCFNumberIntType, &wid)) continue;
109
+
110
+ /* 窗口矩形:CGWindowBounds 就是一个表示 CGRect 的字典,交给它自己解 */
111
+ CGRect rect;
112
+ CFTypeRef boundsRef = CFDictionaryGetValue(w, kCGWindowBounds);
113
+ if (!boundsRef || CFGetTypeID(boundsRef) != CFDictionaryGetTypeID()) continue;
114
+ if (!CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)boundsRef, &rect)) continue;
115
+ if (rect.size.width < 8 || rect.size.height < 8) continue;
116
+
117
+ double layer = numOr(w, kCGWindowLayer, 0);
118
+ double alpha = numOr(w, kCGWindowAlpha, 1);
119
+
120
+ char owner[256];
121
+ CFTypeRef ownerRef = CFDictionaryGetValue(w, kCGWindowOwnerName);
122
+ if (ownerRef && CFGetTypeID(ownerRef) == CFStringGetTypeID()) {
123
+ CFStringGetCString((CFStringRef)ownerRef, owner, sizeof(owner), kCFStringEncodingUTF8);
124
+ } else {
125
+ owner[0] = '\0';
126
+ }
127
+ char safe[512];
128
+ jsonEscape(owner, safe, sizeof(safe));
129
+
130
+ if (!first) printf(",");
131
+ first = 0;
132
+ printf("{\"id\":%d,\"x\":%.1f,\"y\":%.1f,\"w\":%.1f,\"h\":%.1f,\"layer\":%d,\"alpha\":%.2f,\"owner\":\"%s\"}",
133
+ wid, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height,
134
+ (int)layer, alpha, safe);
135
+ }
136
+ printf("]\n");
137
+ if (wins) CFRelease(wins);
138
+ return 0;
139
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yfwu2020/dsh-selection-explain",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "DSH 划词解读:选中文字浮出按钮,点击弹窗流式显示专业中英翻译 + 该文字在当前上下文中的含义详解",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -8,6 +8,7 @@
8
8
  "files": [
9
9
  "lib",
10
10
  "native/mic-probe.c",
11
+ "native/window-list.c",
11
12
  "cordis.patch.yml",
12
13
  "skills",
13
14
  "README.md",