@lattices/cli 0.4.2 → 0.4.5

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 (70) hide show
  1. package/README.md +3 -0
  2. package/app/Info.plist +2 -2
  3. package/app/Lattices.app/Contents/Info.plist +2 -2
  4. package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
  5. package/app/Package.swift +6 -0
  6. package/app/Sources/App.swift +10 -0
  7. package/app/Sources/AppDelegate.swift +90 -34
  8. package/app/Sources/AppShellView.swift +2 -0
  9. package/app/Sources/AppTypeClassifier.swift +36 -0
  10. package/app/Sources/AppUpdater.swift +92 -0
  11. package/app/Sources/CheatSheetHUD.swift +1 -0
  12. package/app/Sources/CliActionLauncher.swift +50 -0
  13. package/app/Sources/CommandModeView.swift +4 -24
  14. package/app/Sources/CompanionActivityLog.swift +70 -0
  15. package/app/Sources/CompanionKeyboardController.swift +141 -0
  16. package/app/Sources/DesktopModel.swift +4 -0
  17. package/app/Sources/HandsOffSession.swift +15 -4
  18. package/app/Sources/HomeDashboardView.swift +18 -10
  19. package/app/Sources/HotkeyStore.swift +8 -5
  20. package/app/Sources/IntentEngine.swift +7 -1
  21. package/app/Sources/LatticesApi.swift +125 -4
  22. package/app/Sources/LatticesCompanionBridgeServer.swift +438 -0
  23. package/app/Sources/LatticesCompanionCockpit.swift +555 -0
  24. package/app/Sources/LatticesCompanionSecurityCoordinator.swift +594 -0
  25. package/app/Sources/LatticesCompanionTrackpadController.swift +204 -0
  26. package/app/Sources/LatticesDeckHost.swift +1463 -0
  27. package/app/Sources/LatticesRuntime.swift +61 -0
  28. package/app/Sources/MainView.swift +351 -191
  29. package/app/Sources/MouseFinder.swift +335 -30
  30. package/app/Sources/MouseGestureConfig.swift +364 -0
  31. package/app/Sources/MouseGestureController.swift +1203 -0
  32. package/app/Sources/MouseInputDeviceStore.swift +98 -0
  33. package/app/Sources/MouseInputEventViewer.swift +272 -0
  34. package/app/Sources/MouseShortcutStore.swift +107 -0
  35. package/app/Sources/OmniSearchView.swift +136 -2
  36. package/app/Sources/OmniSearchWindow.swift +65 -5
  37. package/app/Sources/OnboardingView.swift +30 -16
  38. package/app/Sources/PaletteCommand.swift +26 -6
  39. package/app/Sources/PermissionChecker.swift +76 -2
  40. package/app/Sources/PiAuthNextStepCard.swift +148 -0
  41. package/app/Sources/PiAuthPromptCard.swift +90 -0
  42. package/app/Sources/PiChatDock.swift +137 -74
  43. package/app/Sources/PiChatSession.swift +608 -108
  44. package/app/Sources/PiInstallCallout.swift +86 -0
  45. package/app/Sources/PiProviderSetupCallout.swift +99 -0
  46. package/app/Sources/PiWorkspaceView.swift +174 -77
  47. package/app/Sources/Preferences.swift +78 -0
  48. package/app/Sources/ScreenMapState.swift +91 -31
  49. package/app/Sources/ScreenMapView.swift +510 -524
  50. package/app/Sources/ScreenMapWindowController.swift +12 -4
  51. package/app/Sources/SettingsView.swift +869 -152
  52. package/app/Sources/SystemTelemetryMonitor.swift +273 -0
  53. package/app/Sources/VoiceCommandWindow.swift +23 -2
  54. package/app/Sources/WindowDragSnapController.swift +628 -0
  55. package/app/Sources/WindowTiler.swift +328 -65
  56. package/app/Sources/WorkspaceManager.swift +288 -0
  57. package/bin/assistant-intelligence.ts +874 -0
  58. package/bin/handsoff-infer.ts +16 -209
  59. package/bin/handsoff-worker.ts +45 -258
  60. package/bin/lattices-app.ts +62 -0
  61. package/bin/lattices-dev +4 -0
  62. package/bin/lattices.ts +125 -14
  63. package/docs/agents.md +14 -0
  64. package/docs/api.md +55 -0
  65. package/docs/app.md +3 -0
  66. package/docs/companion-deck.md +180 -0
  67. package/docs/config.md +25 -0
  68. package/docs/tiling-reference.md +55 -0
  69. package/docs/voice-error-model.md +73 -0
  70. package/package.json +2 -1
@@ -0,0 +1,364 @@
1
+ import AppKit
2
+ import Foundation
3
+
4
+ enum MouseGestureDirection: String, CaseIterable, Codable, Equatable {
5
+ case left
6
+ case right
7
+ case up
8
+ case down
9
+ }
10
+
11
+ enum MouseShortcutTriggerKind: String, Codable, Equatable {
12
+ case drag
13
+ }
14
+
15
+ enum MouseShortcutActionType: String, Codable, Equatable {
16
+ case spaceNext = "space.next"
17
+ case spacePrevious = "space.previous"
18
+ case screenMapToggle = "screenmap.toggle"
19
+ case dictationStart = "dictation.start"
20
+ case shortcutSend = "shortcut.send"
21
+ }
22
+
23
+ enum MouseShortcutModifier: String, CaseIterable, Codable, Equatable {
24
+ case command
25
+ case control
26
+ case option
27
+ case shift
28
+
29
+ var appleScriptToken: String {
30
+ switch self {
31
+ case .command: return "command down"
32
+ case .control: return "control down"
33
+ case .option: return "option down"
34
+ case .shift: return "shift down"
35
+ }
36
+ }
37
+
38
+ var displayLabel: String {
39
+ switch self {
40
+ case .command: return "Cmd"
41
+ case .control: return "Ctrl"
42
+ case .option: return "Option"
43
+ case .shift: return "Shift"
44
+ }
45
+ }
46
+ }
47
+
48
+ enum MouseShortcutButton: Hashable, Codable, Equatable {
49
+ case middle
50
+ case button4
51
+ case button5
52
+ case number(Int)
53
+
54
+ init(rawButtonNumber: Int) {
55
+ switch rawButtonNumber {
56
+ case 2: self = .middle
57
+ case 3: self = .button4
58
+ case 4: self = .button5
59
+ default: self = .number(rawButtonNumber)
60
+ }
61
+ }
62
+
63
+ init(from decoder: Decoder) throws {
64
+ let container = try decoder.singleValueContainer()
65
+ if let intValue = try? container.decode(Int.self) {
66
+ self = MouseShortcutButton(rawButtonNumber: intValue)
67
+ return
68
+ }
69
+
70
+ let stringValue = try container.decode(String.self)
71
+ switch stringValue.lowercased() {
72
+ case "middle", "button.middle":
73
+ self = .middle
74
+ case "button4", "button.button4":
75
+ self = .button4
76
+ case "button5", "button.button5":
77
+ self = .button5
78
+ default:
79
+ if let raw = Int(stringValue.filter(\.isNumber)) {
80
+ self = MouseShortcutButton(rawButtonNumber: raw)
81
+ } else {
82
+ throw DecodingError.dataCorruptedError(in: container, debugDescription: "Unsupported mouse button '\(stringValue)'")
83
+ }
84
+ }
85
+ }
86
+
87
+ func encode(to encoder: Encoder) throws {
88
+ var container = encoder.singleValueContainer()
89
+ try container.encode(configValue)
90
+ }
91
+
92
+ var rawButtonNumber: Int {
93
+ switch self {
94
+ case .middle: return 2
95
+ case .button4: return 3
96
+ case .button5: return 4
97
+ case .number(let value): return value
98
+ }
99
+ }
100
+
101
+ var configValue: String {
102
+ switch self {
103
+ case .middle: return "middle"
104
+ case .button4: return "button4"
105
+ case .button5: return "button5"
106
+ case .number(let value): return "button\(value)"
107
+ }
108
+ }
109
+
110
+ var displayLabel: String {
111
+ switch self {
112
+ case .middle: return "Middle Click"
113
+ case .button4: return "Button 4"
114
+ case .button5: return "Button 5"
115
+ case .number(let value): return "Button \(value)"
116
+ }
117
+ }
118
+
119
+ var triggerToken: String {
120
+ switch self {
121
+ case .middle: return "button.middle"
122
+ case .button4: return "button.button4"
123
+ case .button5: return "button.button5"
124
+ case .number(let value): return "button.\(value)"
125
+ }
126
+ }
127
+ }
128
+
129
+ struct MouseShortcutDeviceSelector: Codable, Equatable {
130
+ private enum CodingKeys: String, CodingKey {
131
+ case match
132
+ case vendorId
133
+ case productId
134
+ case locationId
135
+ case product
136
+ case manufacturer
137
+ case transport
138
+ }
139
+
140
+ var match: String?
141
+ var vendorId: Int?
142
+ var productId: Int?
143
+ var locationId: Int?
144
+ var product: String?
145
+ var manufacturer: String?
146
+ var transport: String?
147
+
148
+ static let any = MouseShortcutDeviceSelector(match: "any")
149
+
150
+ init(
151
+ match: String? = "any",
152
+ vendorId: Int? = nil,
153
+ productId: Int? = nil,
154
+ locationId: Int? = nil,
155
+ product: String? = nil,
156
+ manufacturer: String? = nil,
157
+ transport: String? = nil
158
+ ) {
159
+ self.match = match
160
+ self.vendorId = vendorId
161
+ self.productId = productId
162
+ self.locationId = locationId
163
+ self.product = product
164
+ self.manufacturer = manufacturer
165
+ self.transport = transport
166
+ }
167
+
168
+ init(from decoder: Decoder) throws {
169
+ let container = try decoder.singleValueContainer()
170
+ if let stringValue = try? container.decode(String.self) {
171
+ self = MouseShortcutDeviceSelector(match: stringValue)
172
+ return
173
+ }
174
+
175
+ let object = try decoder.container(keyedBy: CodingKeys.self)
176
+ match = try object.decodeIfPresent(String.self, forKey: .match)
177
+ vendorId = try object.decodeIfPresent(Int.self, forKey: .vendorId)
178
+ productId = try object.decodeIfPresent(Int.self, forKey: .productId)
179
+ locationId = try object.decodeIfPresent(Int.self, forKey: .locationId)
180
+ product = try object.decodeIfPresent(String.self, forKey: .product)
181
+ manufacturer = try object.decodeIfPresent(String.self, forKey: .manufacturer)
182
+ transport = try object.decodeIfPresent(String.self, forKey: .transport)
183
+ }
184
+
185
+ func encode(to encoder: Encoder) throws {
186
+ if isAny {
187
+ var container = encoder.singleValueContainer()
188
+ try container.encode("any")
189
+ return
190
+ }
191
+
192
+ var container = encoder.container(keyedBy: CodingKeys.self)
193
+ try container.encodeIfPresent(match, forKey: .match)
194
+ try container.encodeIfPresent(vendorId, forKey: .vendorId)
195
+ try container.encodeIfPresent(productId, forKey: .productId)
196
+ try container.encodeIfPresent(locationId, forKey: .locationId)
197
+ try container.encodeIfPresent(product, forKey: .product)
198
+ try container.encodeIfPresent(manufacturer, forKey: .manufacturer)
199
+ try container.encodeIfPresent(transport, forKey: .transport)
200
+ }
201
+
202
+ var isAny: Bool {
203
+ let normalized = (match ?? "any").lowercased()
204
+ return normalized == "any"
205
+ && vendorId == nil
206
+ && productId == nil
207
+ && locationId == nil
208
+ && product == nil
209
+ && manufacturer == nil
210
+ && transport == nil
211
+ }
212
+
213
+ func matches(_ device: MouseInputDeviceInfo?) -> Bool {
214
+ if isAny { return true }
215
+ guard let device else { return false }
216
+ if let vendorId, vendorId != device.vendorId { return false }
217
+ if let productId, productId != device.productId { return false }
218
+ if let locationId, locationId != device.locationId { return false }
219
+ if let product, device.product?.localizedCaseInsensitiveContains(product) != true { return false }
220
+ if let manufacturer, device.manufacturer?.localizedCaseInsensitiveContains(manufacturer) != true { return false }
221
+ if let transport, device.transport?.localizedCaseInsensitiveContains(transport) != true { return false }
222
+ return true
223
+ }
224
+ }
225
+
226
+ struct MouseShortcutTrigger: Codable, Equatable {
227
+ var button: MouseShortcutButton
228
+ var kind: MouseShortcutTriggerKind
229
+ var direction: MouseGestureDirection
230
+
231
+ var triggerName: String {
232
+ "\(button.triggerToken).\(kind.rawValue).\(direction.rawValue)"
233
+ }
234
+ }
235
+
236
+ struct MouseShortcutKeyStroke: Codable, Equatable {
237
+ var key: String?
238
+ var keyCode: Int?
239
+ var modifiers: [MouseShortcutModifier]
240
+
241
+ var displayLabel: String {
242
+ let keyLabel = key?.uppercased() ?? "KeyCode \(keyCode ?? -1)"
243
+ let parts = modifiers.map(\.displayLabel) + [keyLabel]
244
+ return parts.joined(separator: "+")
245
+ }
246
+ }
247
+
248
+ struct MouseShortcutActionDefinition: Codable, Equatable {
249
+ var type: MouseShortcutActionType
250
+ var shortcut: MouseShortcutKeyStroke?
251
+
252
+ var label: String {
253
+ switch type {
254
+ case .spaceNext:
255
+ return "Next Space"
256
+ case .spacePrevious:
257
+ return "Previous Space"
258
+ case .screenMapToggle:
259
+ return "Screen Map Overview"
260
+ case .dictationStart:
261
+ return "Dictation"
262
+ case .shortcutSend:
263
+ return shortcut?.displayLabel ?? "Send Shortcut"
264
+ }
265
+ }
266
+ }
267
+
268
+ struct MouseShortcutRule: Codable, Equatable, Identifiable {
269
+ var id: String
270
+ var enabled: Bool
271
+ var device: MouseShortcutDeviceSelector
272
+ var trigger: MouseShortcutTrigger
273
+ var action: MouseShortcutActionDefinition
274
+
275
+ var summary: String {
276
+ "\(trigger.triggerName) -> \(action.type.rawValue)"
277
+ }
278
+ }
279
+
280
+ struct MouseShortcutTuning: Codable, Equatable {
281
+ var dragThreshold: CGFloat
282
+ var holdTolerance: CGFloat
283
+ var axisBias: CGFloat
284
+
285
+ static let defaults = MouseShortcutTuning(
286
+ dragThreshold: 68,
287
+ holdTolerance: 10,
288
+ axisBias: 1.2
289
+ )
290
+ }
291
+
292
+ struct MouseShortcutConfig: Codable, Equatable {
293
+ var version: Int
294
+ var tuning: MouseShortcutTuning
295
+ var rules: [MouseShortcutRule]
296
+
297
+ static let defaults = MouseShortcutConfig(
298
+ version: 1,
299
+ tuning: .defaults,
300
+ rules: [
301
+ MouseShortcutRule(
302
+ id: "space-previous",
303
+ enabled: true,
304
+ device: .any,
305
+ trigger: MouseShortcutTrigger(button: .middle, kind: .drag, direction: .left),
306
+ action: MouseShortcutActionDefinition(type: .spacePrevious, shortcut: nil)
307
+ ),
308
+ MouseShortcutRule(
309
+ id: "space-next",
310
+ enabled: true,
311
+ device: .any,
312
+ trigger: MouseShortcutTrigger(button: .middle, kind: .drag, direction: .right),
313
+ action: MouseShortcutActionDefinition(type: .spaceNext, shortcut: nil)
314
+ ),
315
+ MouseShortcutRule(
316
+ id: "screenmap-overview",
317
+ enabled: true,
318
+ device: .any,
319
+ trigger: MouseShortcutTrigger(button: .middle, kind: .drag, direction: .down),
320
+ action: MouseShortcutActionDefinition(type: .screenMapToggle, shortcut: nil)
321
+ ),
322
+ MouseShortcutRule(
323
+ id: "dictation",
324
+ enabled: true,
325
+ device: .any,
326
+ trigger: MouseShortcutTrigger(button: .middle, kind: .drag, direction: .up),
327
+ action: MouseShortcutActionDefinition(type: .dictationStart, shortcut: nil)
328
+ ),
329
+ ]
330
+ )
331
+ }
332
+
333
+ struct MouseShortcutMatchResult {
334
+ let rule: MouseShortcutRule
335
+ let action: MouseShortcutActionDefinition
336
+ let triggerName: String
337
+ }
338
+
339
+ struct MouseShortcutTriggerEvent {
340
+ let button: MouseShortcutButton
341
+ let kind: MouseShortcutTriggerKind
342
+ let direction: MouseGestureDirection
343
+ let device: MouseInputDeviceInfo?
344
+
345
+ var triggerName: String {
346
+ MouseShortcutTrigger(button: button, kind: kind, direction: direction).triggerName
347
+ }
348
+ }
349
+
350
+ struct MouseShortcutObservedEvent {
351
+ let timestamp: Date
352
+ let phase: String
353
+ let buttonNumber: Int
354
+ let location: CGPoint
355
+ let delta: CGPoint
356
+ let modifiers: NSEvent.ModifierFlags
357
+ let frontmostAppName: String?
358
+ let frontmostBundleId: String?
359
+ let candidateTrigger: String?
360
+ let device: MouseInputDeviceInfo?
361
+ let matchedRuleSummary: String?
362
+ let willFire: Bool
363
+ let note: String?
364
+ }