@lattices/cli 0.3.0 → 0.4.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.
- package/README.md +85 -9
- package/app/Info.plist +30 -0
- package/app/Lattices.app/Contents/Info.plist +8 -2
- package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/app/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
- package/app/Lattices.app/Contents/Resources/tap.wav +0 -0
- package/app/Lattices.app/Contents/_CodeSignature/CodeResources +139 -0
- package/app/Lattices.entitlements +15 -0
- package/app/Package.swift +8 -1
- package/app/Resources/tap.wav +0 -0
- package/app/Sources/AdvisorLearningStore.swift +90 -0
- package/app/Sources/AgentSession.swift +377 -0
- package/app/Sources/AppDelegate.swift +45 -12
- package/app/Sources/AppShellView.swift +81 -8
- package/app/Sources/AudioProvider.swift +386 -0
- package/app/Sources/CheatSheetHUD.swift +261 -19
- package/app/Sources/DaemonProtocol.swift +13 -0
- package/app/Sources/DaemonServer.swift +8 -0
- package/app/Sources/DesktopModel.swift +189 -6
- package/app/Sources/DesktopModelTypes.swift +2 -0
- package/app/Sources/DiagnosticLog.swift +104 -2
- package/app/Sources/EventBus.swift +1 -0
- package/app/Sources/HUDBottomBar.swift +279 -0
- package/app/Sources/HUDController.swift +1158 -0
- package/app/Sources/HUDLeftBar.swift +849 -0
- package/app/Sources/HUDMinimap.swift +179 -0
- package/app/Sources/HUDRightBar.swift +774 -0
- package/app/Sources/HUDState.swift +367 -0
- package/app/Sources/HUDTopBar.swift +243 -0
- package/app/Sources/HandsOffSession.swift +802 -0
- package/app/Sources/HomeDashboardView.swift +125 -0
- package/app/Sources/HotkeyManager.swift +2 -0
- package/app/Sources/HotkeyStore.swift +49 -9
- package/app/Sources/IntentEngine.swift +962 -0
- package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
- package/app/Sources/Intents/DistributeIntent.swift +56 -0
- package/app/Sources/Intents/FocusIntent.swift +69 -0
- package/app/Sources/Intents/HelpIntent.swift +41 -0
- package/app/Sources/Intents/KillIntent.swift +47 -0
- package/app/Sources/Intents/LatticeIntent.swift +78 -0
- package/app/Sources/Intents/LaunchIntent.swift +67 -0
- package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
- package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
- package/app/Sources/Intents/ScanIntent.swift +52 -0
- package/app/Sources/Intents/SearchIntent.swift +190 -0
- package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
- package/app/Sources/Intents/TileIntent.swift +61 -0
- package/app/Sources/LatticesApi.swift +1275 -30
- package/app/Sources/LauncherHUD.swift +348 -0
- package/app/Sources/MainView.swift +147 -44
- package/app/Sources/MouseFinder.swift +222 -0
- package/app/Sources/OcrModel.swift +34 -1
- package/app/Sources/OmniSearchState.swift +99 -102
- package/app/Sources/OnboardingView.swift +457 -0
- package/app/Sources/PermissionChecker.swift +2 -12
- package/app/Sources/PiChatDock.swift +454 -0
- package/app/Sources/PiChatSession.swift +815 -0
- package/app/Sources/PiWorkspaceView.swift +364 -0
- package/app/Sources/PlacementSpec.swift +195 -0
- package/app/Sources/Preferences.swift +59 -0
- package/app/Sources/ProjectScanner.swift +58 -45
- package/app/Sources/ScreenMapState.swift +701 -55
- package/app/Sources/ScreenMapView.swift +843 -103
- package/app/Sources/ScreenMapWindowController.swift +22 -0
- package/app/Sources/SessionLayerStore.swift +285 -0
- package/app/Sources/SessionManager.swift +4 -1
- package/app/Sources/SettingsView.swift +186 -3
- package/app/Sources/Theme.swift +9 -8
- package/app/Sources/TmuxModel.swift +7 -0
- package/app/Sources/TmuxQuery.swift +27 -3
- package/app/Sources/VoiceChatView.swift +192 -0
- package/app/Sources/VoiceCommandWindow.swift +1594 -0
- package/app/Sources/VoiceIntentResolver.swift +671 -0
- package/app/Sources/VoxClient.swift +454 -0
- package/app/Sources/WindowTiler.swift +348 -87
- package/app/Sources/WorkspaceManager.swift +127 -18
- package/app/Tests/StageDragTests.swift +333 -0
- package/app/Tests/StageJoinTests.swift +313 -0
- package/app/Tests/StageManagerTests.swift +280 -0
- package/app/Tests/StageTileTests.swift +353 -0
- package/assets/AppIcon.icns +0 -0
- package/bin/client.ts +16 -0
- package/bin/{daemon-client.js → daemon-client.ts} +49 -30
- package/bin/handsoff-infer.ts +280 -0
- package/bin/handsoff-worker.ts +740 -0
- package/bin/lattices-app.ts +338 -0
- package/bin/lattices-dev +208 -0
- package/bin/{lattices.js → lattices.ts} +777 -140
- package/bin/project-twin.ts +645 -0
- package/docs/agent-execution-plan.md +562 -0
- package/docs/agent-layer-guide.md +207 -0
- package/docs/agents.md +142 -0
- package/docs/api.md +153 -34
- package/docs/app.md +29 -1
- package/docs/config.md +5 -1
- package/docs/handsoff-test-scenarios.md +84 -0
- package/docs/layers.md +20 -20
- package/docs/ocr.md +14 -5
- package/docs/overview.md +5 -1
- package/docs/presentation-execution-review.md +491 -0
- package/docs/prompts/hands-off-system.md +374 -0
- package/docs/prompts/hands-off-turn.md +30 -0
- package/docs/prompts/voice-advisor.md +31 -0
- package/docs/prompts/voice-fallback.md +23 -0
- package/docs/tiling-reference.md +167 -0
- package/docs/twins.md +138 -0
- package/docs/voice-command-protocol.md +278 -0
- package/docs/voice.md +219 -0
- package/package.json +29 -11
- package/bin/client.js +0 -4
- package/bin/lattices-app.js +0 -221
|
@@ -15,53 +15,66 @@ class ProjectScanner: ObservableObject {
|
|
|
15
15
|
self.scanRoot = root
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
private static let scanQueue = DispatchQueue(label: "com.lattices.project-scanner", qos: .userInitiated)
|
|
19
|
+
private var scanInFlight = false
|
|
20
|
+
|
|
18
21
|
func scan() {
|
|
19
|
-
|
|
22
|
+
guard !scanInFlight else { return }
|
|
23
|
+
scanInFlight = true
|
|
24
|
+
let root = scanRoot
|
|
25
|
+
|
|
26
|
+
Self.scanQueue.async { [weak self] in
|
|
27
|
+
guard let self else { return }
|
|
28
|
+
let diag = DiagnosticLog.shared
|
|
29
|
+
|
|
30
|
+
// Use find to locate all .lattices.json files — no manual directory walking
|
|
31
|
+
let tFind = diag.startTimed("ProjectScanner: find .lattices.json")
|
|
32
|
+
let task = Process()
|
|
33
|
+
task.executableURL = URL(fileURLWithPath: "/usr/bin/find")
|
|
34
|
+
task.arguments = [root, "-name", ".lattices.json", "-maxdepth", "3", "-not", "-path", "*/.git/*", "-not", "-path", "*/node_modules/*"]
|
|
35
|
+
let pipe = Pipe()
|
|
36
|
+
task.standardOutput = pipe
|
|
37
|
+
task.standardError = FileHandle.nullDevice
|
|
38
|
+
try? task.run()
|
|
39
|
+
task.waitUntilExit()
|
|
40
|
+
diag.finish(tFind)
|
|
41
|
+
|
|
42
|
+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
|
43
|
+
let output = String(data: data, encoding: .utf8) ?? ""
|
|
44
|
+
let configPaths = output.split(separator: "\n").map(String.init).filter { !$0.isEmpty }
|
|
45
|
+
|
|
46
|
+
let tParse = diag.startTimed("ProjectScanner: parse \(configPaths.count) configs")
|
|
47
|
+
var found: [Project] = []
|
|
48
|
+
|
|
49
|
+
for configPath in configPaths.sorted() {
|
|
50
|
+
let projectPath = (configPath as NSString).deletingLastPathComponent
|
|
51
|
+
let name = (projectPath as NSString).lastPathComponent
|
|
52
|
+
let (devCmd, pm) = self.detectDevCommand(at: projectPath)
|
|
53
|
+
let paneInfo = self.readPaneInfo(at: configPath)
|
|
54
|
+
|
|
55
|
+
var project = Project(
|
|
56
|
+
id: projectPath,
|
|
57
|
+
path: projectPath,
|
|
58
|
+
name: name,
|
|
59
|
+
devCommand: devCmd,
|
|
60
|
+
packageManager: pm,
|
|
61
|
+
hasConfig: true,
|
|
62
|
+
paneCount: paneInfo.count,
|
|
63
|
+
paneNames: paneInfo.names,
|
|
64
|
+
paneSummary: paneInfo.summary,
|
|
65
|
+
isRunning: false
|
|
66
|
+
)
|
|
67
|
+
project.isRunning = self.isSessionRunning(project.sessionName)
|
|
68
|
+
found.append(project)
|
|
69
|
+
}
|
|
70
|
+
diag.finish(tParse)
|
|
20
71
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
let pipe = Pipe()
|
|
27
|
-
task.standardOutput = pipe
|
|
28
|
-
task.standardError = FileHandle.nullDevice
|
|
29
|
-
try? task.run()
|
|
30
|
-
task.waitUntilExit()
|
|
31
|
-
diag.finish(tFind)
|
|
32
|
-
|
|
33
|
-
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
|
34
|
-
let output = String(data: data, encoding: .utf8) ?? ""
|
|
35
|
-
let configPaths = output.split(separator: "\n").map(String.init).filter { !$0.isEmpty }
|
|
36
|
-
|
|
37
|
-
let tParse = diag.startTimed("ProjectScanner: parse \(configPaths.count) configs")
|
|
38
|
-
var found: [Project] = []
|
|
39
|
-
|
|
40
|
-
for configPath in configPaths.sorted() {
|
|
41
|
-
let projectPath = (configPath as NSString).deletingLastPathComponent
|
|
42
|
-
let name = (projectPath as NSString).lastPathComponent
|
|
43
|
-
let (devCmd, pm) = detectDevCommand(at: projectPath)
|
|
44
|
-
let paneInfo = readPaneInfo(at: configPath)
|
|
45
|
-
|
|
46
|
-
var project = Project(
|
|
47
|
-
id: projectPath,
|
|
48
|
-
path: projectPath,
|
|
49
|
-
name: name,
|
|
50
|
-
devCommand: devCmd,
|
|
51
|
-
packageManager: pm,
|
|
52
|
-
hasConfig: true,
|
|
53
|
-
paneCount: paneInfo.count,
|
|
54
|
-
paneNames: paneInfo.names,
|
|
55
|
-
paneSummary: paneInfo.summary,
|
|
56
|
-
isRunning: false
|
|
57
|
-
)
|
|
58
|
-
project.isRunning = isSessionRunning(project.sessionName)
|
|
59
|
-
found.append(project)
|
|
72
|
+
diag.info("ProjectScanner: found \(found.count) projects (\(found.filter(\.isRunning).count) running)")
|
|
73
|
+
DispatchQueue.main.async {
|
|
74
|
+
self.projects = found
|
|
75
|
+
self.scanInFlight = false
|
|
76
|
+
}
|
|
60
77
|
}
|
|
61
|
-
diag.finish(tParse)
|
|
62
|
-
|
|
63
|
-
diag.info("ProjectScanner: found \(found.count) projects (\(found.filter(\.isRunning).count) running)")
|
|
64
|
-
DispatchQueue.main.async { self.projects = found }
|
|
65
78
|
}
|
|
66
79
|
|
|
67
80
|
func refreshStatus() {
|
|
@@ -113,7 +126,7 @@ class ProjectScanner: ObservableObject {
|
|
|
113
126
|
return (panes.count, labels, labels.joined(separator: " · "))
|
|
114
127
|
}
|
|
115
128
|
|
|
116
|
-
private static
|
|
129
|
+
private static var tmuxPath: String { TmuxQuery.resolvedPath ?? "/opt/homebrew/bin/tmux" }
|
|
117
130
|
|
|
118
131
|
private func isSessionRunning(_ name: String) -> Bool {
|
|
119
132
|
let task = Process()
|