@zenalexa/unicli 0.223.4 → 0.224.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 (130) hide show
  1. package/AGENTS.md +5 -5
  2. package/README.md +4 -4
  3. package/README.zh-CN.md +4 -4
  4. package/dist/adapters/marxists-cn/archive.d.ts +61 -0
  5. package/dist/adapters/marxists-cn/archive.d.ts.map +1 -0
  6. package/dist/adapters/marxists-cn/archive.js +861 -0
  7. package/dist/adapters/marxists-cn/archive.js.map +1 -0
  8. package/dist/adapters/twitter/lists-extra.d.ts +17 -1
  9. package/dist/adapters/twitter/lists-extra.d.ts.map +1 -1
  10. package/dist/adapters/twitter/lists-extra.js +123 -21
  11. package/dist/adapters/twitter/lists-extra.js.map +1 -1
  12. package/dist/adapters/twitter/post.js +1 -0
  13. package/dist/adapters/twitter/post.js.map +1 -1
  14. package/dist/adapters/twitter/thread.d.ts +13 -1
  15. package/dist/adapters/twitter/thread.d.ts.map +1 -1
  16. package/dist/adapters/twitter/thread.js +76 -33
  17. package/dist/adapters/twitter/thread.js.map +1 -1
  18. package/dist/cli.d.ts.map +1 -1
  19. package/dist/cli.js +3 -0
  20. package/dist/cli.js.map +1 -1
  21. package/dist/commands/architecture.d.ts +21 -0
  22. package/dist/commands/architecture.d.ts.map +1 -0
  23. package/dist/commands/architecture.js +47 -0
  24. package/dist/commands/architecture.js.map +1 -0
  25. package/dist/commands/compute.d.ts.map +1 -1
  26. package/dist/commands/compute.js +31 -6
  27. package/dist/commands/compute.js.map +1 -1
  28. package/dist/commands/doctor-compute.d.ts.map +1 -1
  29. package/dist/commands/doctor-compute.js +88 -1
  30. package/dist/commands/doctor-compute.js.map +1 -1
  31. package/dist/compute/action-execution.d.ts +30 -0
  32. package/dist/compute/action-execution.d.ts.map +1 -0
  33. package/dist/compute/action-execution.js +112 -0
  34. package/dist/compute/action-execution.js.map +1 -0
  35. package/dist/compute/capture-reference.d.ts.map +1 -1
  36. package/dist/compute/capture-reference.js +6 -1
  37. package/dist/compute/capture-reference.js.map +1 -1
  38. package/dist/compute/capture.d.ts +2 -0
  39. package/dist/compute/capture.d.ts.map +1 -1
  40. package/dist/compute/capture.js +6 -1
  41. package/dist/compute/capture.js.map +1 -1
  42. package/dist/compute/cursor-visual-style.d.ts +35 -0
  43. package/dist/compute/cursor-visual-style.d.ts.map +1 -0
  44. package/dist/compute/cursor-visual-style.js +39 -0
  45. package/dist/compute/cursor-visual-style.js.map +1 -0
  46. package/dist/compute/linux-overlay.d.ts +38 -0
  47. package/dist/compute/linux-overlay.d.ts.map +1 -0
  48. package/dist/compute/linux-overlay.js +274 -0
  49. package/dist/compute/linux-overlay.js.map +1 -0
  50. package/dist/compute/macos-overlay.d.ts +64 -0
  51. package/dist/compute/macos-overlay.d.ts.map +1 -0
  52. package/dist/compute/macos-overlay.js +590 -0
  53. package/dist/compute/macos-overlay.js.map +1 -0
  54. package/dist/compute/overlay-daemon.d.ts +47 -0
  55. package/dist/compute/overlay-daemon.d.ts.map +1 -0
  56. package/dist/compute/overlay-daemon.js +206 -0
  57. package/dist/compute/overlay-daemon.js.map +1 -0
  58. package/dist/compute/overlay.d.ts +42 -0
  59. package/dist/compute/overlay.d.ts.map +1 -0
  60. package/dist/compute/overlay.js +111 -0
  61. package/dist/compute/overlay.js.map +1 -0
  62. package/dist/compute/platform-overlays.d.ts +20 -0
  63. package/dist/compute/platform-overlays.d.ts.map +1 -0
  64. package/dist/compute/platform-overlays.js +31 -0
  65. package/dist/compute/platform-overlays.js.map +1 -0
  66. package/dist/compute/visual-timeline.d.ts +132 -0
  67. package/dist/compute/visual-timeline.d.ts.map +1 -0
  68. package/dist/compute/visual-timeline.js +431 -0
  69. package/dist/compute/visual-timeline.js.map +1 -0
  70. package/dist/compute/windows-overlay.d.ts +38 -0
  71. package/dist/compute/windows-overlay.d.ts.map +1 -0
  72. package/dist/compute/windows-overlay.js +282 -0
  73. package/dist/compute/windows-overlay.js.map +1 -0
  74. package/dist/core/architecture-tree.d.ts +68 -0
  75. package/dist/core/architecture-tree.d.ts.map +1 -0
  76. package/dist/core/architecture-tree.js +215 -0
  77. package/dist/core/architecture-tree.js.map +1 -0
  78. package/dist/discovery/aliases.d.ts.map +1 -1
  79. package/dist/discovery/aliases.js +93 -0
  80. package/dist/discovery/aliases.js.map +1 -1
  81. package/dist/discovery/core-catalog.d.ts.map +1 -1
  82. package/dist/discovery/core-catalog.js +14 -0
  83. package/dist/discovery/core-catalog.js.map +1 -1
  84. package/dist/discovery/intents.d.ts.map +1 -1
  85. package/dist/discovery/intents.js +124 -0
  86. package/dist/discovery/intents.js.map +1 -1
  87. package/dist/discovery/loader.d.ts +12 -6
  88. package/dist/discovery/loader.d.ts.map +1 -1
  89. package/dist/discovery/loader.js +37 -10
  90. package/dist/discovery/loader.js.map +1 -1
  91. package/dist/discovery/search.d.ts +27 -28
  92. package/dist/discovery/search.d.ts.map +1 -1
  93. package/dist/discovery/search.js +118 -120
  94. package/dist/discovery/search.js.map +1 -1
  95. package/dist/engine/text-normalize.d.ts +14 -0
  96. package/dist/engine/text-normalize.d.ts.map +1 -1
  97. package/dist/engine/text-normalize.js +64 -0
  98. package/dist/engine/text-normalize.js.map +1 -1
  99. package/dist/fast-path/handlers/discovery.d.ts +12 -5
  100. package/dist/fast-path/handlers/discovery.d.ts.map +1 -1
  101. package/dist/fast-path/handlers/discovery.js +42 -7
  102. package/dist/fast-path/handlers/discovery.js.map +1 -1
  103. package/dist/manifest-compact.txt +2 -2
  104. package/dist/manifest.json +352 -3
  105. package/dist/mcp/profiles/computer-use.d.ts.map +1 -1
  106. package/dist/mcp/profiles/computer-use.js +76 -8
  107. package/dist/mcp/profiles/computer-use.js.map +1 -1
  108. package/dist/registry.d.ts +14 -5
  109. package/dist/registry.d.ts.map +1 -1
  110. package/dist/registry.js +33 -6
  111. package/dist/registry.js.map +1 -1
  112. package/dist/transport/cascade.d.ts +1 -0
  113. package/dist/transport/cascade.d.ts.map +1 -1
  114. package/dist/transport/cascade.js +2 -2
  115. package/dist/transport/cascade.js.map +1 -1
  116. package/docs/operate/compute.md +66 -1
  117. package/docs/operate/troubleshooting.md +42 -0
  118. package/package.json +9 -5
  119. package/server.json +3 -3
  120. package/skills/unicli/SKILL.md +1 -1
  121. package/skills/unicli-claude-code/SKILL.md +1 -1
  122. package/skills/unicli-hermes/SKILL.md +1 -1
  123. package/src/adapters/marxists-cn/archive.test.ts +173 -0
  124. package/src/adapters/marxists-cn/archive.ts +1049 -0
  125. package/src/adapters/twitter/lists-extra.test.ts +115 -0
  126. package/src/adapters/twitter/lists-extra.ts +146 -26
  127. package/src/adapters/twitter/post.ts +1 -0
  128. package/src/adapters/twitter/thread.test.ts +25 -1
  129. package/src/adapters/twitter/thread.ts +99 -47
  130. package/dist/manifest-search.json +0 -1
@@ -0,0 +1,590 @@
1
+ /**
2
+ * @owner src/compute/macos-overlay.ts
3
+ * @does Render compute visual_action evidence through a macOS AppKit full-screen HUD.
4
+ * @needs Swift runtime, AppKit, src/compute/overlay.ts
5
+ * @feeds future computer-use native overlay orchestration
6
+ * @breaks Non-click-through or key windows can steal focus from the real action transport.
7
+ * @invariants The overlay is visual-only, click-through, non-key, and spans every visible screen.
8
+ * @side-effects launches a Swift/AppKit helper on macOS and may keep a daemon process per provider.
9
+ * @perf one persistent Swift process per daemon provider; one-shot provider spawns per render.
10
+ * @concurrency daemon provider serializes render requests; native AppKit state is process-local
11
+ * @test tests/unit/compute-macos-overlay-swift.test.ts
12
+ * @stability experimental
13
+ * @since 0.224.0
14
+ */
15
+ import { spawn } from "node:child_process";
16
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
17
+ import { tmpdir } from "node:os";
18
+ import { join } from "node:path";
19
+ import { computeOverlayRequestFromAction, } from "./overlay.js";
20
+ import { StdioComputeOverlayDaemonSession, } from "./overlay-daemon.js";
21
+ export class MacosAppKitOverlayProvider {
22
+ provider = "macos-appkit";
23
+ platform;
24
+ shell;
25
+ scriptPath;
26
+ lastPoint;
27
+ constructor(opts = {}) {
28
+ this.platform = opts.platform ?? process.platform;
29
+ this.shell = opts.shell ?? defaultShell;
30
+ this.scriptPath = opts.scriptPath;
31
+ }
32
+ currentPoint() {
33
+ return this.lastPoint;
34
+ }
35
+ async render(action) {
36
+ const request = computeOverlayRequestFromAction(action);
37
+ if (!request) {
38
+ return { provider: "macos-appkit", status: "not_requested" };
39
+ }
40
+ if (this.platform !== "darwin") {
41
+ return { provider: "macos-appkit", status: "unavailable" };
42
+ }
43
+ let tmpRoot;
44
+ const scriptPath = this.scriptPath ??
45
+ join((tmpRoot = await mkdtemp(join(tmpdir(), "unicli-overlay-"))), "main.swift");
46
+ try {
47
+ if (!this.scriptPath) {
48
+ await writeFile(scriptPath, buildMacosOverlaySwiftScript(), "utf8");
49
+ }
50
+ const result = await this.shell.run("swift", [scriptPath], {
51
+ input: JSON.stringify(request),
52
+ timeoutMs: Math.max(1_000, request.duration_ms + 1_500),
53
+ });
54
+ const status = parseOverlayStatus(result.stdout);
55
+ if (status.status === "arrived") {
56
+ this.lastPoint = pointFromOverlayTarget(request);
57
+ }
58
+ return status;
59
+ }
60
+ catch (error) {
61
+ return {
62
+ provider: "macos-appkit",
63
+ status: "failed",
64
+ error: errorMessage(error),
65
+ };
66
+ }
67
+ finally {
68
+ if (tmpRoot)
69
+ await rm(tmpRoot, { recursive: true, force: true });
70
+ }
71
+ }
72
+ }
73
+ export class MacosAppKitOverlayDaemonProvider {
74
+ provider = "macos-appkit";
75
+ platform;
76
+ scriptPath;
77
+ sessionFactory;
78
+ session;
79
+ tmpRoot;
80
+ lastPoint;
81
+ constructor(opts = {}) {
82
+ this.platform = opts.platform ?? process.platform;
83
+ this.scriptPath = opts.scriptPath;
84
+ this.sessionFactory = opts.sessionFactory;
85
+ }
86
+ currentPoint() {
87
+ return this.lastPoint;
88
+ }
89
+ async render(action) {
90
+ const request = computeOverlayRequestFromAction(action);
91
+ if (!request) {
92
+ return { provider: "macos-appkit", status: "not_requested" };
93
+ }
94
+ if (this.platform !== "darwin") {
95
+ return { provider: "macos-appkit", status: "unavailable" };
96
+ }
97
+ try {
98
+ const session = await this.ensureSession();
99
+ const status = await session.render(request, Math.max(1_000, request.duration_ms + 1_500));
100
+ if (status.status === "arrived") {
101
+ this.lastPoint = pointFromOverlayTarget(request);
102
+ }
103
+ return status;
104
+ }
105
+ catch (error) {
106
+ return {
107
+ provider: "macos-appkit",
108
+ status: "failed",
109
+ error: errorMessage(error),
110
+ };
111
+ }
112
+ }
113
+ async close() {
114
+ await this.session?.close();
115
+ this.session = undefined;
116
+ if (this.tmpRoot) {
117
+ await rm(this.tmpRoot, { recursive: true, force: true });
118
+ this.tmpRoot = undefined;
119
+ }
120
+ }
121
+ async ensureSession() {
122
+ if (this.session)
123
+ return this.session;
124
+ if (this.sessionFactory) {
125
+ this.session = await this.sessionFactory();
126
+ return this.session;
127
+ }
128
+ const scriptPath = this.scriptPath ??
129
+ join((this.tmpRoot = await mkdtemp(join(tmpdir(), "unicli-overlayd-"))), "main.swift");
130
+ if (!this.scriptPath) {
131
+ await writeFile(scriptPath, buildMacosOverlayDaemonSwiftScript(), "utf8");
132
+ }
133
+ this.session = new StdioComputeOverlayDaemonSession("swift", [scriptPath]);
134
+ return this.session;
135
+ }
136
+ }
137
+ export function buildMacosOverlaySwiftScript() {
138
+ return String.raw `
139
+ import AppKit
140
+ import Foundation
141
+ import QuartzCore
142
+
143
+ let cursorVisualStyle = "mac-glass-pointer-v1"
144
+ let cursorSkin = "mac-pointer"
145
+
146
+ struct OverlaySample: Decodable {
147
+ let at_ms: Double
148
+ let x: Double
149
+ let y: Double
150
+ let screenIndex: Int?
151
+ }
152
+
153
+ struct OverlayAffordance: Decodable {
154
+ let cursor: String?
155
+ let halo: String?
156
+ let trail: Bool?
157
+ let click_ripple: Bool?
158
+ }
159
+
160
+ struct OverlayRequest: Decodable {
161
+ let action_id: String
162
+ let action: String
163
+ let visual_style: String?
164
+ let state: String?
165
+ let affordance: OverlayAffordance?
166
+ let target: OverlaySample
167
+ let duration_ms: Double
168
+ let samples: [OverlaySample]
169
+ }
170
+
171
+ final class ComputeOverlayWindow: NSWindow {
172
+ override var canBecomeKey: Bool { false }
173
+ override var canBecomeMain: Bool { false }
174
+ }
175
+
176
+ final class ComputeOverlayView: NSView {
177
+ private let haloLayer = CAShapeLayer()
178
+ private let stateLayer = CAShapeLayer()
179
+ private let coreLayer = CAShapeLayer()
180
+ private let trailLayer = CAShapeLayer()
181
+ private let screenFrame: NSRect
182
+
183
+ init(frame: NSRect, screenFrame: NSRect) {
184
+ self.screenFrame = screenFrame
185
+ super.init(frame: frame)
186
+ wantsLayer = true
187
+ layer?.backgroundColor = NSColor.clear.cgColor
188
+ trailLayer.fillColor = NSColor.clear.cgColor
189
+ trailLayer.strokeColor = NSColor(calibratedRed: 0.76, green: 0.60, blue: 0.32, alpha: 0.52).cgColor
190
+ trailLayer.lineWidth = 2
191
+ trailLayer.lineCap = .round
192
+ haloLayer.fillColor = NSColor(calibratedRed: 0.98, green: 0.96, blue: 0.90, alpha: 0.98).cgColor
193
+ haloLayer.strokeColor = NSColor(calibratedRed: 0.09, green: 0.07, blue: 0.05, alpha: 0.96).cgColor
194
+ haloLayer.lineWidth = 2.25
195
+ haloLayer.shadowColor = NSColor(calibratedWhite: 0.0, alpha: 0.45).cgColor
196
+ haloLayer.shadowRadius = 10
197
+ haloLayer.shadowOpacity = 0.72
198
+ haloLayer.shadowOffset = .zero
199
+ stateLayer.fillColor = NSColor.clear.cgColor
200
+ stateLayer.strokeColor = NSColor(calibratedRed: 0.76, green: 0.60, blue: 0.32, alpha: 0.78).cgColor
201
+ stateLayer.lineWidth = 1.5
202
+ stateLayer.opacity = 0
203
+ coreLayer.fillColor = NSColor.clear.cgColor
204
+ coreLayer.strokeColor = NSColor(calibratedWhite: 1.0, alpha: 0.72).cgColor
205
+ coreLayer.lineWidth = 1
206
+ layer?.addSublayer(trailLayer)
207
+ layer?.addSublayer(haloLayer)
208
+ layer?.addSublayer(stateLayer)
209
+ layer?.addSublayer(coreLayer)
210
+ }
211
+
212
+ required init?(coder: NSCoder) { nil }
213
+
214
+ func update(point: CGPoint, trail: [CGPoint], request: OverlayRequest, elapsedMs: Double, durationMs: Double) {
215
+ CATransaction.begin()
216
+ CATransaction.setDisableActions(true)
217
+ let local = CGPoint(x: point.x - screenFrame.minX, y: point.y - screenFrame.minY)
218
+ let hotspot = local
219
+ let pointerPath = CGMutablePath()
220
+ pointerPath.move(to: local)
221
+ pointerPath.addLine(to: CGPoint(x: local.x, y: local.y + 45))
222
+ pointerPath.addLine(to: CGPoint(x: local.x + 13, y: local.y + 32))
223
+ pointerPath.addLine(to: CGPoint(x: local.x + 21, y: local.y + 55))
224
+ pointerPath.addLine(to: CGPoint(x: local.x + 31, y: local.y + 51))
225
+ pointerPath.addLine(to: CGPoint(x: local.x + 23, y: local.y + 29))
226
+ pointerPath.addLine(to: CGPoint(x: local.x + 43, y: local.y + 29))
227
+ pointerPath.closeSubpath()
228
+ let highlightPath = CGMutablePath()
229
+ highlightPath.move(to: CGPoint(x: local.x + 6, y: local.y + 8))
230
+ highlightPath.addLine(to: CGPoint(x: local.x + 6, y: local.y + 34))
231
+ let trailPath = CGMutablePath()
232
+ for (index, global) in trail.enumerated() {
233
+ let p = CGPoint(x: global.x - screenFrame.minX, y: global.y - screenFrame.minY)
234
+ if index == 0 { trailPath.move(to: p) } else { trailPath.addLine(to: p) }
235
+ }
236
+ let state = request.state ?? ""
237
+ let halo = request.affordance?.halo ?? ""
238
+ let clickRipple = request.affordance?.click_ripple ?? false
239
+ let pressProgress = durationMs > 0 ? elapsedMs / durationMs : 1
240
+ let isPressure = (state == "press" || halo == "pressure-bloom" || clickRipple) && pressProgress >= 0.78
241
+ let isOrbit = state == "wait" || halo == "busy-orbit"
242
+ let statePath = CGMutablePath()
243
+ statePath.addEllipse(in: CGRect(x: local.x - 14, y: local.y - 14, width: 30, height: 30))
244
+ haloLayer.path = pointerPath
245
+ coreLayer.path = highlightPath
246
+ trailLayer.path = trailPath
247
+ stateLayer.path = statePath
248
+ stateLayer.opacity = isPressure || isOrbit ? 1 : 0
249
+ stateLayer.lineDashPattern = isOrbit ? [4 as NSNumber, 5 as NSNumber] : nil
250
+ CATransaction.commit()
251
+ }
252
+ }
253
+
254
+ let data = FileHandle.standardInput.readDataToEndOfFile()
255
+ let request = try JSONDecoder().decode(OverlayRequest.self, from: data)
256
+ let displayHeight = NSScreen.screens.map { $0.frame.maxY }.max() ?? 0
257
+
258
+ func appKitPoint(_ sample: OverlaySample) -> CGPoint {
259
+ CGPoint(x: sample.x, y: displayHeight - sample.y)
260
+ }
261
+
262
+ func sampleAt(elapsedMs: Double) -> OverlaySample {
263
+ guard let first = request.samples.first else { return request.target }
264
+ var previous = first
265
+ for sample in request.samples.dropFirst() {
266
+ if sample.at_ms >= elapsedMs {
267
+ let span = max(1, sample.at_ms - previous.at_ms)
268
+ let t = min(1, max(0, (elapsedMs - previous.at_ms) / span))
269
+ return OverlaySample(
270
+ at_ms: elapsedMs,
271
+ x: previous.x + (sample.x - previous.x) * t,
272
+ y: previous.y + (sample.y - previous.y) * t,
273
+ screenIndex: sample.screenIndex ?? previous.screenIndex
274
+ )
275
+ }
276
+ previous = sample
277
+ }
278
+ return request.target
279
+ }
280
+
281
+ let app = NSApplication.shared
282
+ app.setActivationPolicy(.accessory)
283
+ var views: [ComputeOverlayView] = []
284
+ for screen in NSScreen.screens {
285
+ let window = ComputeOverlayWindow(
286
+ contentRect: screen.frame,
287
+ styleMask: [.borderless],
288
+ backing: .buffered,
289
+ defer: false,
290
+ screen: screen
291
+ )
292
+ window.level = .screenSaver
293
+ window.backgroundColor = .clear
294
+ window.isOpaque = false
295
+ window.hasShadow = false
296
+ window.ignoresMouseEvents = true
297
+ window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .stationary]
298
+ let view = ComputeOverlayView(frame: NSRect(origin: .zero, size: screen.frame.size), screenFrame: screen.frame)
299
+ window.contentView = view
300
+ window.orderFrontRegardless()
301
+ views.append(view)
302
+ }
303
+
304
+ let start = ProcessInfo.processInfo.systemUptime
305
+ let duration = max(120, request.duration_ms)
306
+ Timer.scheduledTimer(withTimeInterval: 1.0 / 60.0, repeats: true) { timer in
307
+ let elapsed = (ProcessInfo.processInfo.systemUptime - start) * 1000
308
+ let sample = sampleAt(elapsedMs: elapsed)
309
+ let point = appKitPoint(sample)
310
+ let trail = request.samples.filter { $0.at_ms <= elapsed }.suffix(10).map(appKitPoint)
311
+ for view in views { view.update(point: point, trail: trail, request: request, elapsedMs: elapsed, durationMs: duration) }
312
+ if elapsed >= duration {
313
+ print("{\"provider\":\"macos-appkit\",\"status\":\"arrived\",\"acknowledged_at_ms\":\(Int(duration))}")
314
+ fflush(stdout)
315
+ timer.invalidate()
316
+ app.terminate(nil)
317
+ }
318
+ }
319
+
320
+ app.run()
321
+ `;
322
+ }
323
+ export function buildMacosOverlayDaemonSwiftScript() {
324
+ return String.raw `
325
+ import AppKit
326
+ import Foundation
327
+ import QuartzCore
328
+
329
+ let cursorVisualStyle = "mac-glass-pointer-v1"
330
+ let cursorSkin = "mac-pointer"
331
+
332
+ struct OverlaySample: Decodable {
333
+ let at_ms: Double
334
+ let x: Double
335
+ let y: Double
336
+ let screenIndex: Int?
337
+ }
338
+
339
+ struct OverlayAffordance: Decodable {
340
+ let cursor: String?
341
+ let halo: String?
342
+ let trail: Bool?
343
+ let click_ripple: Bool?
344
+ }
345
+
346
+ struct OverlayRequest: Decodable {
347
+ let action_id: String
348
+ let action: String
349
+ let visual_style: String?
350
+ let state: String?
351
+ let affordance: OverlayAffordance?
352
+ let target: OverlaySample
353
+ let duration_ms: Double
354
+ let samples: [OverlaySample]
355
+ }
356
+
357
+ final class ComputeOverlayWindow: NSWindow {
358
+ override var canBecomeKey: Bool { false }
359
+ override var canBecomeMain: Bool { false }
360
+ }
361
+
362
+ final class ComputeOverlayView: NSView {
363
+ private let haloLayer = CAShapeLayer()
364
+ private let stateLayer = CAShapeLayer()
365
+ private let coreLayer = CAShapeLayer()
366
+ private let trailLayer = CAShapeLayer()
367
+ private let screenFrame: NSRect
368
+
369
+ init(frame: NSRect, screenFrame: NSRect) {
370
+ self.screenFrame = screenFrame
371
+ super.init(frame: frame)
372
+ wantsLayer = true
373
+ layer?.backgroundColor = NSColor.clear.cgColor
374
+ trailLayer.fillColor = NSColor.clear.cgColor
375
+ trailLayer.strokeColor = NSColor(calibratedRed: 0.76, green: 0.60, blue: 0.32, alpha: 0.52).cgColor
376
+ trailLayer.lineWidth = 2
377
+ trailLayer.lineCap = .round
378
+ haloLayer.fillColor = NSColor(calibratedRed: 0.98, green: 0.96, blue: 0.90, alpha: 0.98).cgColor
379
+ haloLayer.strokeColor = NSColor(calibratedRed: 0.09, green: 0.07, blue: 0.05, alpha: 0.96).cgColor
380
+ haloLayer.lineWidth = 2.25
381
+ haloLayer.shadowColor = NSColor(calibratedWhite: 0.0, alpha: 0.45).cgColor
382
+ haloLayer.shadowRadius = 10
383
+ haloLayer.shadowOpacity = 0.72
384
+ haloLayer.shadowOffset = .zero
385
+ stateLayer.fillColor = NSColor.clear.cgColor
386
+ stateLayer.strokeColor = NSColor(calibratedRed: 0.76, green: 0.60, blue: 0.32, alpha: 0.78).cgColor
387
+ stateLayer.lineWidth = 1.5
388
+ stateLayer.opacity = 0
389
+ coreLayer.fillColor = NSColor.clear.cgColor
390
+ coreLayer.strokeColor = NSColor(calibratedWhite: 1.0, alpha: 0.72).cgColor
391
+ coreLayer.lineWidth = 1
392
+ layer?.addSublayer(trailLayer)
393
+ layer?.addSublayer(haloLayer)
394
+ layer?.addSublayer(stateLayer)
395
+ layer?.addSublayer(coreLayer)
396
+ }
397
+
398
+ required init?(coder: NSCoder) { nil }
399
+
400
+ func update(point: CGPoint, trail: [CGPoint], request: OverlayRequest, elapsedMs: Double, durationMs: Double) {
401
+ CATransaction.begin()
402
+ CATransaction.setDisableActions(true)
403
+ let local = CGPoint(x: point.x - screenFrame.minX, y: point.y - screenFrame.minY)
404
+ let hotspot = local
405
+ let pointerPath = CGMutablePath()
406
+ pointerPath.move(to: local)
407
+ pointerPath.addLine(to: CGPoint(x: local.x, y: local.y + 45))
408
+ pointerPath.addLine(to: CGPoint(x: local.x + 13, y: local.y + 32))
409
+ pointerPath.addLine(to: CGPoint(x: local.x + 21, y: local.y + 55))
410
+ pointerPath.addLine(to: CGPoint(x: local.x + 31, y: local.y + 51))
411
+ pointerPath.addLine(to: CGPoint(x: local.x + 23, y: local.y + 29))
412
+ pointerPath.addLine(to: CGPoint(x: local.x + 43, y: local.y + 29))
413
+ pointerPath.closeSubpath()
414
+ let highlightPath = CGMutablePath()
415
+ highlightPath.move(to: CGPoint(x: local.x + 6, y: local.y + 8))
416
+ highlightPath.addLine(to: CGPoint(x: local.x + 6, y: local.y + 34))
417
+ let trailPath = CGMutablePath()
418
+ for (index, global) in trail.enumerated() {
419
+ let p = CGPoint(x: global.x - screenFrame.minX, y: global.y - screenFrame.minY)
420
+ if index == 0 { trailPath.move(to: p) } else { trailPath.addLine(to: p) }
421
+ }
422
+ let state = request.state ?? ""
423
+ let halo = request.affordance?.halo ?? ""
424
+ let clickRipple = request.affordance?.click_ripple ?? false
425
+ let pressProgress = durationMs > 0 ? elapsedMs / durationMs : 1
426
+ let isPressure = (state == "press" || halo == "pressure-bloom" || clickRipple) && pressProgress >= 0.78
427
+ let isOrbit = state == "wait" || halo == "busy-orbit"
428
+ let statePath = CGMutablePath()
429
+ statePath.addEllipse(in: CGRect(x: local.x - 14, y: local.y - 14, width: 30, height: 30))
430
+ haloLayer.path = pointerPath
431
+ coreLayer.path = highlightPath
432
+ trailLayer.path = trailPath
433
+ stateLayer.path = statePath
434
+ stateLayer.opacity = isPressure || isOrbit ? 1 : 0
435
+ stateLayer.lineDashPattern = isOrbit ? [4 as NSNumber, 5 as NSNumber] : nil
436
+ CATransaction.commit()
437
+ }
438
+ }
439
+
440
+ let app = NSApplication.shared
441
+ app.setActivationPolicy(.accessory)
442
+ let displayHeight = NSScreen.screens.map { $0.frame.maxY }.max() ?? 0
443
+ var views: [ComputeOverlayView] = []
444
+ var activeTimer: Timer?
445
+
446
+ for screen in NSScreen.screens {
447
+ let window = ComputeOverlayWindow(
448
+ contentRect: screen.frame,
449
+ styleMask: [.borderless],
450
+ backing: .buffered,
451
+ defer: false,
452
+ screen: screen
453
+ )
454
+ window.level = .screenSaver
455
+ window.backgroundColor = .clear
456
+ window.isOpaque = false
457
+ window.hasShadow = false
458
+ window.ignoresMouseEvents = true
459
+ window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .stationary]
460
+ let view = ComputeOverlayView(frame: NSRect(origin: .zero, size: screen.frame.size), screenFrame: screen.frame)
461
+ window.contentView = view
462
+ window.orderFrontRegardless()
463
+ views.append(view)
464
+ }
465
+
466
+ print("{\"provider\":\"macos-appkit\",\"status\":\"ready\"}")
467
+ fflush(stdout)
468
+
469
+ func appKitPoint(_ sample: OverlaySample) -> CGPoint {
470
+ CGPoint(x: sample.x, y: displayHeight - sample.y)
471
+ }
472
+
473
+ func sampleAt(_ request: OverlayRequest, elapsedMs: Double) -> OverlaySample {
474
+ guard let first = request.samples.first else { return request.target }
475
+ var previous = first
476
+ for sample in request.samples.dropFirst() {
477
+ if sample.at_ms >= elapsedMs {
478
+ let span = max(1, sample.at_ms - previous.at_ms)
479
+ let t = min(1, max(0, (elapsedMs - previous.at_ms) / span))
480
+ return OverlaySample(
481
+ at_ms: elapsedMs,
482
+ x: previous.x + (sample.x - previous.x) * t,
483
+ y: previous.y + (sample.y - previous.y) * t,
484
+ screenIndex: sample.screenIndex ?? previous.screenIndex
485
+ )
486
+ }
487
+ previous = sample
488
+ }
489
+ return request.target
490
+ }
491
+
492
+ func render(request: OverlayRequest) {
493
+ activeTimer?.invalidate()
494
+ let start = ProcessInfo.processInfo.systemUptime
495
+ let duration = max(120, request.duration_ms)
496
+ activeTimer = Timer.scheduledTimer(withTimeInterval: 1.0 / 60.0, repeats: true) { timer in
497
+ let elapsed = (ProcessInfo.processInfo.systemUptime - start) * 1000
498
+ let sample = sampleAt(request, elapsedMs: elapsed)
499
+ let point = appKitPoint(sample)
500
+ let trail = request.samples.filter { $0.at_ms <= elapsed }.suffix(10).map(appKitPoint)
501
+ for view in views { view.update(point: point, trail: trail, request: request, elapsedMs: elapsed, durationMs: duration) }
502
+ if elapsed >= duration {
503
+ print("{\"provider\":\"macos-appkit\",\"status\":\"arrived\",\"acknowledged_at_ms\":\(Int(duration))}")
504
+ fflush(stdout)
505
+ timer.invalidate()
506
+ activeTimer = nil
507
+ }
508
+ }
509
+ }
510
+
511
+ DispatchQueue.global(qos: .userInitiated).async {
512
+ while let line = readLine() {
513
+ guard let data = line.data(using: .utf8) else { continue }
514
+ do {
515
+ let request = try JSONDecoder().decode(OverlayRequest.self, from: data)
516
+ DispatchQueue.main.async {
517
+ render(request: request)
518
+ }
519
+ } catch {
520
+ print("{\"provider\":\"macos-appkit\",\"status\":\"failed\",\"error\":\"invalid request\"}")
521
+ fflush(stdout)
522
+ }
523
+ }
524
+ DispatchQueue.main.async { app.terminate(nil) }
525
+ }
526
+
527
+ app.run()
528
+ `;
529
+ }
530
+ function parseOverlayStatus(stdout) {
531
+ try {
532
+ const value = JSON.parse(stdout.trim());
533
+ if (value.provider === "macos-appkit" && typeof value.status === "string") {
534
+ return value;
535
+ }
536
+ }
537
+ catch {
538
+ // handled below
539
+ }
540
+ return {
541
+ provider: "macos-appkit",
542
+ status: "failed",
543
+ error: "overlay sidecar returned invalid JSON",
544
+ };
545
+ }
546
+ function pointFromOverlayTarget(request) {
547
+ return {
548
+ x: request.target.x,
549
+ y: request.target.y,
550
+ coordinate_space: {
551
+ kind: "screen-pixels",
552
+ origin: "top-left",
553
+ ...(request.target.screenIndex !== undefined
554
+ ? { screenIndex: request.target.screenIndex }
555
+ : {}),
556
+ },
557
+ };
558
+ }
559
+ function errorMessage(error) {
560
+ return error instanceof Error ? error.message : String(error);
561
+ }
562
+ const defaultShell = {
563
+ run(command, args, opts) {
564
+ return new Promise((resolve, reject) => {
565
+ const child = spawn(command, [...args], {
566
+ stdio: ["pipe", "pipe", "pipe"],
567
+ timeout: opts?.timeoutMs ?? 2_000,
568
+ });
569
+ const stdoutChunks = [];
570
+ const stderrChunks = [];
571
+ child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
572
+ child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
573
+ child.on("error", reject);
574
+ child.on("close", (code) => {
575
+ const stdout = Buffer.concat(stdoutChunks).toString("utf8");
576
+ const stderr = Buffer.concat(stderrChunks).toString("utf8");
577
+ if (code !== 0) {
578
+ reject(new Error(stderr || `${command} exited with code ${code}`));
579
+ return;
580
+ }
581
+ resolve({ stdout, stderr });
582
+ });
583
+ if (opts?.input !== undefined) {
584
+ child.stdin.write(opts.input);
585
+ }
586
+ child.stdin.end();
587
+ });
588
+ },
589
+ };
590
+ //# sourceMappingURL=macos-overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-overlay.js","sourceRoot":"","sources":["../../src/compute/macos-overlay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @owner src/compute/overlay-daemon.ts
3
+ * @does Manage JSONL stdio sessions for native compute overlay HUD daemons.
4
+ * @needs child_process spawn, readline, visual overlay status protocol
5
+ * @feeds macOS AppKit, Windows Win32, and Linux GTK overlay providers
6
+ * @breaks Missing ready separation causes cold-start time to consume render animation timeouts.
7
+ * @invariants A daemon must emit provider/status=ready before render requests are written.
8
+ * @side-effects Starts and kills native helper processes.
9
+ * @perf One persistent process per overlay provider instance.
10
+ * @concurrency Render calls are serialized through one active JSONL request.
11
+ * @test tests/unit/compute-macos-overlay-swift.test.ts
12
+ * @stability experimental
13
+ * @since 0.224.0
14
+ */
15
+ import type { ComputeOverlayRequest } from "./overlay.js";
16
+ import type { ComputeVisualOverlayStatus } from "./visual-timeline.js";
17
+ export interface ComputeOverlayDaemonSession {
18
+ render(request: ComputeOverlayRequest, timeoutMs: number): Promise<ComputeVisualOverlayStatus>;
19
+ close(): Promise<void>;
20
+ }
21
+ export declare class StdioComputeOverlayDaemonSession implements ComputeOverlayDaemonSession {
22
+ private readonly command;
23
+ private readonly args;
24
+ private child;
25
+ private lines;
26
+ private active;
27
+ private readiness;
28
+ private readonly queue;
29
+ private closed;
30
+ private readonly readyTimeoutMs;
31
+ constructor(command: string, args: readonly string[], opts?: {
32
+ readyTimeoutMs?: number;
33
+ });
34
+ render(request: ComputeOverlayRequest, timeoutMs: number): Promise<ComputeVisualOverlayStatus>;
35
+ close(): Promise<void>;
36
+ private processNext;
37
+ private writeActiveCall;
38
+ private ensureReadyChild;
39
+ private ensureChild;
40
+ private handleLine;
41
+ private createReadiness;
42
+ private resolveReadinessIfReady;
43
+ private rejectActive;
44
+ private rejectQueue;
45
+ private rejectReadiness;
46
+ }
47
+ //# sourceMappingURL=overlay-daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-daemon.d.ts","sourceRoot":"","sources":["../../src/compute/overlay-daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CACJ,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,gCAAiC,YAAW,2BAA2B;IAUhF,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVvB,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;IAClD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAGrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACxC,IAAI,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO;IAKxC,MAAM,CACJ,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,0BAA0B,CAAC;IAOhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,eAAe;YAcT,gBAAgB;IAO9B,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,eAAe;CAMxB"}