@lattices/cli 0.3.0 → 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.
Files changed (95) hide show
  1. package/README.md +85 -9
  2. package/app/Package.swift +8 -1
  3. package/app/Sources/AdvisorLearningStore.swift +90 -0
  4. package/app/Sources/AgentSession.swift +377 -0
  5. package/app/Sources/AppDelegate.swift +44 -12
  6. package/app/Sources/AppShellView.swift +81 -8
  7. package/app/Sources/AudioProvider.swift +386 -0
  8. package/app/Sources/CheatSheetHUD.swift +261 -19
  9. package/app/Sources/DaemonProtocol.swift +13 -0
  10. package/app/Sources/DaemonServer.swift +8 -0
  11. package/app/Sources/DesktopModel.swift +164 -5
  12. package/app/Sources/DesktopModelTypes.swift +2 -0
  13. package/app/Sources/DiagnosticLog.swift +104 -2
  14. package/app/Sources/EventBus.swift +1 -0
  15. package/app/Sources/HUDBottomBar.swift +279 -0
  16. package/app/Sources/HUDController.swift +1158 -0
  17. package/app/Sources/HUDLeftBar.swift +849 -0
  18. package/app/Sources/HUDMinimap.swift +179 -0
  19. package/app/Sources/HUDRightBar.swift +774 -0
  20. package/app/Sources/HUDState.swift +367 -0
  21. package/app/Sources/HUDTopBar.swift +243 -0
  22. package/app/Sources/HandsOffSession.swift +733 -0
  23. package/app/Sources/HomeDashboardView.swift +125 -0
  24. package/app/Sources/HotkeyManager.swift +2 -0
  25. package/app/Sources/HotkeyStore.swift +45 -9
  26. package/app/Sources/IntentEngine.swift +925 -0
  27. package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
  28. package/app/Sources/Intents/DistributeIntent.swift +56 -0
  29. package/app/Sources/Intents/FocusIntent.swift +69 -0
  30. package/app/Sources/Intents/HelpIntent.swift +41 -0
  31. package/app/Sources/Intents/KillIntent.swift +47 -0
  32. package/app/Sources/Intents/LatticeIntent.swift +78 -0
  33. package/app/Sources/Intents/LaunchIntent.swift +67 -0
  34. package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
  35. package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
  36. package/app/Sources/Intents/ScanIntent.swift +52 -0
  37. package/app/Sources/Intents/SearchIntent.swift +190 -0
  38. package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
  39. package/app/Sources/Intents/TileIntent.swift +61 -0
  40. package/app/Sources/LatticesApi.swift +1235 -30
  41. package/app/Sources/LauncherHUD.swift +348 -0
  42. package/app/Sources/MainView.swift +147 -44
  43. package/app/Sources/OcrModel.swift +34 -1
  44. package/app/Sources/OmniSearchState.swift +99 -102
  45. package/app/Sources/OnboardingView.swift +457 -0
  46. package/app/Sources/PermissionChecker.swift +2 -12
  47. package/app/Sources/PiChatDock.swift +454 -0
  48. package/app/Sources/PiChatSession.swift +815 -0
  49. package/app/Sources/PiWorkspaceView.swift +364 -0
  50. package/app/Sources/PlacementSpec.swift +195 -0
  51. package/app/Sources/Preferences.swift +59 -0
  52. package/app/Sources/ProjectScanner.swift +1 -1
  53. package/app/Sources/ScreenMapState.swift +701 -55
  54. package/app/Sources/ScreenMapView.swift +843 -103
  55. package/app/Sources/ScreenMapWindowController.swift +22 -0
  56. package/app/Sources/SessionLayerStore.swift +285 -0
  57. package/app/Sources/SessionManager.swift +4 -1
  58. package/app/Sources/SettingsView.swift +186 -3
  59. package/app/Sources/Theme.swift +9 -8
  60. package/app/Sources/TmuxModel.swift +7 -0
  61. package/app/Sources/TmuxQuery.swift +27 -3
  62. package/app/Sources/VoiceChatView.swift +192 -0
  63. package/app/Sources/VoiceCommandWindow.swift +1594 -0
  64. package/app/Sources/VoiceIntentResolver.swift +671 -0
  65. package/app/Sources/VoxClient.swift +454 -0
  66. package/app/Sources/WindowTiler.swift +348 -87
  67. package/app/Sources/WorkspaceManager.swift +127 -18
  68. package/bin/client.ts +16 -0
  69. package/bin/{daemon-client.js → daemon-client.ts} +49 -30
  70. package/bin/handsoff-infer.ts +280 -0
  71. package/bin/handsoff-worker.ts +731 -0
  72. package/bin/{lattices-app.js → lattices-app.ts} +67 -32
  73. package/bin/lattices-dev +160 -0
  74. package/bin/{lattices.js → lattices.ts} +600 -137
  75. package/bin/project-twin.ts +645 -0
  76. package/docs/agent-execution-plan.md +562 -0
  77. package/docs/agents.md +142 -0
  78. package/docs/api.md +153 -34
  79. package/docs/app.md +29 -1
  80. package/docs/config.md +5 -1
  81. package/docs/handsoff-test-scenarios.md +84 -0
  82. package/docs/layers.md +20 -20
  83. package/docs/ocr.md +14 -5
  84. package/docs/overview.md +5 -1
  85. package/docs/presentation-execution-review.md +491 -0
  86. package/docs/prompts/hands-off-system.md +374 -0
  87. package/docs/prompts/hands-off-turn.md +30 -0
  88. package/docs/prompts/voice-advisor.md +31 -0
  89. package/docs/prompts/voice-fallback.md +23 -0
  90. package/docs/tiling-reference.md +167 -0
  91. package/docs/twins.md +138 -0
  92. package/docs/voice-command-protocol.md +278 -0
  93. package/docs/voice.md +219 -0
  94. package/package.json +21 -10
  95. package/bin/client.js +0 -4
@@ -0,0 +1,125 @@
1
+ import SwiftUI
2
+
3
+ struct HomeDashboardView: View {
4
+ var onNavigate: ((AppPage) -> Void)? = nil
5
+
6
+ @ObservedObject private var scanner = ProjectScanner.shared
7
+
8
+ var body: some View {
9
+ VStack(spacing: 0) {
10
+ hero
11
+
12
+ Rectangle()
13
+ .fill(Palette.border)
14
+ .frame(height: 0.5)
15
+
16
+ MainView(scanner: scanner, layout: .embedded)
17
+ }
18
+ .background(Palette.bg)
19
+ }
20
+
21
+ private var hero: some View {
22
+ VStack(alignment: .leading, spacing: 18) {
23
+ HStack(alignment: .top) {
24
+ VStack(alignment: .leading, spacing: 8) {
25
+ Text("Lattices Home")
26
+ .font(Typo.heading(18))
27
+ .foregroundColor(Palette.text)
28
+
29
+ Text("Launch workspaces, jump into the screen map, or open a full Pi session from one place.")
30
+ .font(Typo.mono(11))
31
+ .foregroundColor(Palette.textDim)
32
+ .fixedSize(horizontal: false, vertical: true)
33
+ }
34
+
35
+ Spacer()
36
+ }
37
+
38
+ HStack(spacing: 10) {
39
+ homeActionCard(
40
+ title: "Screen Map",
41
+ subtitle: "Spatial window layout",
42
+ icon: "rectangle.3.group",
43
+ tint: Palette.running
44
+ ) {
45
+ onNavigate?(.screenMap)
46
+ }
47
+
48
+ homeActionCard(
49
+ title: "Desktop Inventory",
50
+ subtitle: "Enumerate displays and spaces",
51
+ icon: "macwindow.on.rectangle",
52
+ tint: Palette.detach
53
+ ) {
54
+ onNavigate?(.desktopInventory)
55
+ }
56
+
57
+ homeActionCard(
58
+ title: "Pi Workspace",
59
+ subtitle: "Standalone conversation surface",
60
+ icon: "terminal",
61
+ tint: Palette.text
62
+ ) {
63
+ onNavigate?(.pi)
64
+ }
65
+ }
66
+ }
67
+ .padding(.horizontal, 16)
68
+ .padding(.vertical, 16)
69
+ .background(
70
+ LinearGradient(
71
+ colors: [
72
+ Palette.running.opacity(0.08),
73
+ Color.black.opacity(0.18),
74
+ ],
75
+ startPoint: .topLeading,
76
+ endPoint: .bottomTrailing
77
+ )
78
+ )
79
+ }
80
+
81
+ private func homeActionCard(
82
+ title: String,
83
+ subtitle: String,
84
+ icon: String,
85
+ tint: Color,
86
+ action: @escaping () -> Void
87
+ ) -> some View {
88
+ Button(action: action) {
89
+ VStack(alignment: .leading, spacing: 10) {
90
+ HStack {
91
+ Image(systemName: icon)
92
+ .font(.system(size: 12, weight: .semibold))
93
+ .foregroundColor(tint)
94
+
95
+ Spacer()
96
+
97
+ Circle()
98
+ .fill(tint.opacity(0.85))
99
+ .frame(width: 6, height: 6)
100
+ }
101
+
102
+ Text(title)
103
+ .font(Typo.monoBold(12))
104
+ .foregroundColor(Palette.text)
105
+
106
+ Text(subtitle)
107
+ .font(Typo.mono(10))
108
+ .foregroundColor(Palette.textMuted)
109
+ .multilineTextAlignment(.leading)
110
+ .fixedSize(horizontal: false, vertical: true)
111
+ }
112
+ .frame(maxWidth: .infinity, alignment: .leading)
113
+ .padding(12)
114
+ .background(
115
+ RoundedRectangle(cornerRadius: 8)
116
+ .fill(Palette.surface.opacity(0.7))
117
+ .overlay(
118
+ RoundedRectangle(cornerRadius: 8)
119
+ .strokeBorder(tint.opacity(0.18), lineWidth: 0.5)
120
+ )
121
+ )
122
+ }
123
+ .buttonStyle(.plain)
124
+ }
125
+ }
@@ -35,6 +35,7 @@ class HotkeyManager {
35
35
  nil,
36
36
  &hotkeyID
37
37
  )
38
+ DiagnosticLog.shared.info("HotkeyManager: fired id=\(hotkeyID.id)")
38
39
  hotkeyCallbacks[hotkeyID.id]?()
39
40
  return noErr
40
41
  },
@@ -176,6 +177,7 @@ class HotkeyManager {
176
177
  )
177
178
  if let ref {
178
179
  hotKeyRefs[id] = ref
180
+ DiagnosticLog.shared.info("HotkeyManager: registered id=\(id) keyCode=\(keyCode) mods=\(modifiers)")
179
181
  } else {
180
182
  DiagnosticLog.shared.warn("HotkeyManager: failed to register id=\(id) keyCode=\(keyCode) mods=\(modifiers) status=\(status)")
181
183
  }
@@ -20,8 +20,13 @@ enum HotkeyAction: String, CaseIterable, Codable {
20
20
  case cheatSheet
21
21
  case desktopInventory
22
22
  case omniSearch
23
+ case voiceCommand
24
+ case handsOff
25
+ case unifiedWindow
26
+ case hud
23
27
  // Layers
24
28
  case layer1, layer2, layer3, layer4, layer5, layer6, layer7, layer8, layer9
29
+ case layerNext, layerPrev, layerTag
25
30
  // Tiling
26
31
  case tileLeft, tileRight, tileMaximize, tileCenter
27
32
  case tileTopLeft, tileTopRight, tileBottomLeft, tileBottomRight
@@ -36,6 +41,10 @@ enum HotkeyAction: String, CaseIterable, Codable {
36
41
  case .cheatSheet: return "Cheat Sheet"
37
42
  case .desktopInventory: return "Desktop Inventory"
38
43
  case .omniSearch: return "Omni Search"
44
+ case .voiceCommand: return "Voice Command"
45
+ case .handsOff: return "Hands-Off Mode"
46
+ case .unifiedWindow: return "Unified Window"
47
+ case .hud: return "HUD"
39
48
  case .layer1: return "Layer 1"
40
49
  case .layer2: return "Layer 2"
41
50
  case .layer3: return "Layer 3"
@@ -45,6 +54,9 @@ enum HotkeyAction: String, CaseIterable, Codable {
45
54
  case .layer7: return "Layer 7"
46
55
  case .layer8: return "Layer 8"
47
56
  case .layer9: return "Layer 9"
57
+ case .layerNext: return "Next Layer"
58
+ case .layerPrev: return "Previous Layer"
59
+ case .layerTag: return "Tag Window"
48
60
  case .tileLeft: return "Tile Left"
49
61
  case .tileRight: return "Tile Right"
50
62
  case .tileMaximize: return "Maximize"
@@ -64,9 +76,10 @@ enum HotkeyAction: String, CaseIterable, Codable {
64
76
 
65
77
  var group: HotkeyGroup {
66
78
  switch self {
67
- case .palette, .screenMap, .bezel, .cheatSheet, .desktopInventory, .omniSearch: return .app
79
+ case .palette, .screenMap, .bezel, .cheatSheet, .desktopInventory, .omniSearch, .voiceCommand, .handsOff, .unifiedWindow, .hud: return .app
68
80
  case .layer1, .layer2, .layer3, .layer4, .layer5,
69
- .layer6, .layer7, .layer8, .layer9: return .layers
81
+ .layer6, .layer7, .layer8, .layer9,
82
+ .layerNext, .layerPrev, .layerTag: return .layers
70
83
  default: return .tiling
71
84
  }
72
85
  }
@@ -79,6 +92,10 @@ enum HotkeyAction: String, CaseIterable, Codable {
79
92
  case .cheatSheet: return 202
80
93
  case .desktopInventory: return 203
81
94
  case .omniSearch: return 204
95
+ case .voiceCommand: return 205
96
+ case .handsOff: return 206
97
+ case .unifiedWindow: return 207
98
+ case .hud: return 208
82
99
  case .layer1: return 101
83
100
  case .layer2: return 102
84
101
  case .layer3: return 103
@@ -88,6 +105,9 @@ enum HotkeyAction: String, CaseIterable, Codable {
88
105
  case .layer7: return 107
89
106
  case .layer8: return 108
90
107
  case .layer9: return 109
108
+ case .layerNext: return 110
109
+ case .layerPrev: return 111
110
+ case .layerTag: return 112
91
111
  case .tileLeft: return 300
92
112
  case .tileRight: return 301
93
113
  case .tileMaximize: return 302
@@ -178,6 +198,14 @@ class HotkeyStore: ObservableObject {
178
198
  @Published var bindings: [HotkeyAction: KeyBinding]
179
199
  private var callbacks: [HotkeyAction: () -> Void] = [:]
180
200
 
201
+ private func instrumentedCallback(for action: HotkeyAction, callback: @escaping () -> Void) -> () -> Void {
202
+ {
203
+ let timed = DiagnosticLog.shared.startTimed("Hotkey \(action.label)")
204
+ callback()
205
+ DiagnosticLog.shared.finish(timed)
206
+ }
207
+ }
208
+
181
209
  static let defaultBindings: [HotkeyAction: KeyBinding] = {
182
210
  var d = [HotkeyAction: KeyBinding]()
183
211
  let hyper = UInt32(cmdKey | controlKey | optionKey | shiftKey)
@@ -195,11 +223,14 @@ class HotkeyStore: ObservableObject {
195
223
 
196
224
  // App
197
225
  bind(.palette, 46, cmdShift) // Cmd+Shift+M
198
- bind(.screenMap, 18, hyper) // Hyper+1
226
+ bind(.unifiedWindow, 18, hyper) // Hyper+1 (Screen Map + Desktop Inventory)
199
227
  bind(.bezel, 19, hyper) // Hyper+2
200
- bind(.cheatSheet, 20, hyper) // Hyper+3
201
- bind(.desktopInventory, 21, hyper) // Hyper+4
228
+ bind(.hud, 20, hyper) // Hyper+3 (HUD overlay)
229
+ bind(.voiceCommand, 21, hyper) // Hyper+4 (moved from Hyper+3)
230
+ let cmdCtrl = UInt32(cmdKey | controlKey)
231
+ bind(.handsOff, 46, cmdCtrl) // Ctrl+Cmd+M
202
232
  bind(.omniSearch, 23, hyper) // Hyper+5
233
+ bind(.cheatSheet, 22, hyper) // Hyper+6
203
234
 
204
235
  // Layers: Cmd+Option+1-9
205
236
  let layerKeyCodes: [UInt32] = [18, 19, 20, 21, 23, 22, 26, 28, 25]
@@ -207,6 +238,11 @@ class HotkeyStore: ObservableObject {
207
238
  bind(action, layerKeyCodes[i], cmdOpt)
208
239
  }
209
240
 
241
+ // Layer cycling: Cmd+Option+Arrow / Cmd+Option+T
242
+ bind(.layerNext, 124, cmdOpt) // Cmd+Opt+→
243
+ bind(.layerPrev, 123, cmdOpt) // Cmd+Opt+←
244
+ bind(.layerTag, 17, cmdOpt) // Cmd+Opt+T
245
+
210
246
  // Tiling: Ctrl+Option for all
211
247
  bind(.tileLeft, 123, ctrlOpt) // Ctrl+Opt+←
212
248
  bind(.tileRight, 124, ctrlOpt) // Ctrl+Opt+→
@@ -263,7 +299,7 @@ class HotkeyStore: ObservableObject {
263
299
  id: action.carbonID,
264
300
  keyCode: binding.keyCode,
265
301
  modifiers: binding.carbonModifiers,
266
- callback: callback
302
+ callback: instrumentedCallback(for: action, callback: callback)
267
303
  )
268
304
  }
269
305
 
@@ -283,7 +319,7 @@ class HotkeyStore: ObservableObject {
283
319
  id: action.carbonID,
284
320
  keyCode: binding.keyCode,
285
321
  modifiers: binding.carbonModifiers,
286
- callback: callback
322
+ callback: instrumentedCallback(for: action, callback: callback)
287
323
  )
288
324
  }
289
325
  }
@@ -300,7 +336,7 @@ class HotkeyStore: ObservableObject {
300
336
  id: action.carbonID,
301
337
  keyCode: defaultBinding.keyCode,
302
338
  modifiers: defaultBinding.carbonModifiers,
303
- callback: callback
339
+ callback: instrumentedCallback(for: action, callback: callback)
304
340
  )
305
341
  }
306
342
  }
@@ -318,7 +354,7 @@ class HotkeyStore: ObservableObject {
318
354
  id: action.carbonID,
319
355
  keyCode: binding.keyCode,
320
356
  modifiers: binding.carbonModifiers,
321
- callback: callback
357
+ callback: instrumentedCallback(for: action, callback: callback)
322
358
  )
323
359
  }
324
360
  }