@lattices/cli 0.4.1 → 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.
- package/README.md +3 -0
- package/app/Info.plist +2 -2
- package/app/Lattices.app/Contents/Info.plist +2 -2
- package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/app/Package.swift +6 -0
- package/app/Sources/ActionRow.swift +43 -26
- package/app/Sources/App.swift +10 -0
- package/app/Sources/AppDelegate.swift +91 -30
- package/app/Sources/AppShellView.swift +2 -0
- package/app/Sources/AppTypeClassifier.swift +36 -0
- package/app/Sources/AppUpdater.swift +92 -0
- package/app/Sources/CheatSheetHUD.swift +1 -0
- package/app/Sources/CliActionLauncher.swift +50 -0
- package/app/Sources/CommandModeView.swift +4 -24
- package/app/Sources/CompanionActivityLog.swift +70 -0
- package/app/Sources/CompanionKeyboardController.swift +141 -0
- package/app/Sources/DesktopModel.swift +4 -0
- package/app/Sources/HandsOffSession.swift +53 -16
- package/app/Sources/HomeDashboardView.swift +18 -10
- package/app/Sources/HotkeyStore.swift +8 -5
- package/app/Sources/IntentEngine.swift +7 -1
- package/app/Sources/LatticesApi.swift +125 -4
- package/app/Sources/LatticesCompanionBridgeServer.swift +438 -0
- package/app/Sources/LatticesCompanionCockpit.swift +555 -0
- package/app/Sources/LatticesCompanionSecurityCoordinator.swift +594 -0
- package/app/Sources/LatticesCompanionTrackpadController.swift +204 -0
- package/app/Sources/LatticesDeckHost.swift +1463 -0
- package/app/Sources/LatticesRuntime.swift +61 -0
- package/app/Sources/MainView.swift +398 -186
- package/app/Sources/MouseFinder.swift +335 -30
- package/app/Sources/MouseGestureConfig.swift +364 -0
- package/app/Sources/MouseGestureController.swift +1203 -0
- package/app/Sources/MouseInputDeviceStore.swift +98 -0
- package/app/Sources/MouseInputEventViewer.swift +272 -0
- package/app/Sources/MouseShortcutStore.swift +107 -0
- package/app/Sources/OmniSearchView.swift +136 -2
- package/app/Sources/OmniSearchWindow.swift +65 -5
- package/app/Sources/OnboardingView.swift +30 -16
- package/app/Sources/PaletteCommand.swift +26 -6
- package/app/Sources/PermissionChecker.swift +76 -2
- package/app/Sources/PiAuthNextStepCard.swift +148 -0
- package/app/Sources/PiAuthPromptCard.swift +90 -0
- package/app/Sources/PiChatDock.swift +137 -74
- package/app/Sources/PiChatSession.swift +608 -108
- package/app/Sources/PiInstallCallout.swift +86 -0
- package/app/Sources/PiProviderSetupCallout.swift +99 -0
- package/app/Sources/PiWorkspaceView.swift +174 -77
- package/app/Sources/Preferences.swift +78 -0
- package/app/Sources/ScreenMapState.swift +91 -31
- package/app/Sources/ScreenMapView.swift +510 -524
- package/app/Sources/ScreenMapWindowController.swift +12 -4
- package/app/Sources/SettingsView.swift +869 -152
- package/app/Sources/SystemTelemetryMonitor.swift +273 -0
- package/app/Sources/VoiceCommandWindow.swift +23 -2
- package/app/Sources/WindowDragSnapController.swift +628 -0
- package/app/Sources/WindowTiler.swift +328 -65
- package/app/Sources/WorkspaceManager.swift +288 -0
- package/bin/assistant-intelligence.ts +874 -0
- package/bin/handsoff-infer.ts +16 -209
- package/bin/handsoff-worker.ts +45 -258
- package/bin/lattices-app.ts +65 -1
- package/bin/lattices-dev +4 -0
- package/bin/lattices.ts +125 -14
- package/docs/agents.md +14 -0
- package/docs/api.md +55 -0
- package/docs/app.md +3 -0
- package/docs/companion-deck.md +180 -0
- package/docs/config.md +25 -0
- package/docs/tiling-reference.md +55 -0
- package/docs/voice-error-model.md +73 -0
- package/package.json +4 -2
package/docs/tiling-reference.md
CHANGED
|
@@ -81,6 +81,56 @@ typed placement model internally:
|
|
|
81
81
|
|
|
82
82
|
That is what keeps CLI, daemon, voice, and hands-off execution aligned.
|
|
83
83
|
|
|
84
|
+
## Drag Snap Zones
|
|
85
|
+
|
|
86
|
+
The menu bar app can also use placement specs as drag-to-snap targets.
|
|
87
|
+
When you drag a window, Lattices shows faint landing zones plus a live
|
|
88
|
+
preview of the resulting frame. Releasing over a zone tiles the dragged
|
|
89
|
+
window to that placement. Hold `Command` while dragging to reveal snap
|
|
90
|
+
mode, and release `Command` to drop back to a normal free drag without
|
|
91
|
+
ending the gesture.
|
|
92
|
+
|
|
93
|
+
The recommended agent-owned config lives in `~/.lattices/snap-zones.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"enabled": true,
|
|
98
|
+
"modifier": "command",
|
|
99
|
+
"zoneOpacity": 0.08,
|
|
100
|
+
"highlightOpacity": 0.18,
|
|
101
|
+
"previewOpacity": 0.14,
|
|
102
|
+
"rules": [
|
|
103
|
+
{
|
|
104
|
+
"id": "left-edge",
|
|
105
|
+
"label": "Left",
|
|
106
|
+
"placement": "left",
|
|
107
|
+
"trigger": { "x": 0.0, "y": 0.18, "w": 0.12, "h": 0.64 },
|
|
108
|
+
"priority": 10
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "notes-rail",
|
|
112
|
+
"label": "Notes",
|
|
113
|
+
"placement": { "x": 0.68, "y": 0.0, "w": 0.32, "h": 1.0 },
|
|
114
|
+
"trigger": { "x": 0.88, "y": 0.18, "w": 0.12, "h": 0.64 },
|
|
115
|
+
"priority": 30
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Notes:
|
|
122
|
+
|
|
123
|
+
- `rules` is the preferred list key. `zones` is still accepted for backward compatibility.
|
|
124
|
+
- `modifier` accepts `command`, `option`, `control`, or `shift`.
|
|
125
|
+
- `placement` can be a named placement/preset string or raw fractions.
|
|
126
|
+
- `trigger` uses normalized `(x, y, w, h)` fractions of the screen's
|
|
127
|
+
visible area, with `y = 0` at the top.
|
|
128
|
+
- `priority` breaks ties when trigger regions overlap.
|
|
129
|
+
- `trigger` can also be a named placement or preset string if you want
|
|
130
|
+
the trigger region itself to reuse an existing tile definition.
|
|
131
|
+
- The older `~/.lattices/grid.json` `snapZones` section still works, but
|
|
132
|
+
`~/.lattices/snap-zones.json` is the cleaner file for agents to edit.
|
|
133
|
+
|
|
84
134
|
## Execution Paths
|
|
85
135
|
|
|
86
136
|
The old split-brain tiling logic has been collapsed toward a shared path.
|
|
@@ -146,6 +196,11 @@ These are composed from multiple `tile_window` actions:
|
|
|
146
196
|
| Eight-up (4×2) | All eight `*-*-fourth` positions |
|
|
147
197
|
| Distribute | Single `distribute` intent (auto-grid) |
|
|
148
198
|
|
|
199
|
+
CLI shortcuts compile into the same distributor:
|
|
200
|
+
|
|
201
|
+
- `lattices tile family` → smart-grid the frontmost app's visible windows
|
|
202
|
+
- `lattices distribute iTerm2 right` → smart-grid visible iTerm windows inside the right half
|
|
203
|
+
|
|
149
204
|
## HandsOff Smart Distribution
|
|
150
205
|
|
|
151
206
|
When the LLM sends multiple `tile_window` actions targeting the **same position**, `HandsOffSession.distributeTileActions()` subdivides:
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Voice Error Model
|
|
2
|
+
|
|
3
|
+
## Goal + anchors
|
|
4
|
+
|
|
5
|
+
Use one error vocabulary for Mac voice capture/execution and iPad relay/status. The canonical protocol says Lattices borrows Vox for capture and never owns the mic directly (`docs/voice-command-protocol.md:5-7`), but the shared runtime already has a cross-platform `DeckVoiceState` slot (`swift/Sources/DeckKit/DeckRuntimeSnapshot.swift:49-68`). Current Mac code exposes local strings (`VoxError`, `executionResult`) instead of structured errors (`app/Sources/VoxClient.swift:43-59`, `app/Sources/AudioProvider.swift:343-349`); iPad has only a generic `errorMessage` (`iOS/LatticesCompanion/Sources/DeckStore.swift:18`). Normalize at DeckKit, then let each surface render the same object.
|
|
6
|
+
|
|
7
|
+
## Error structure
|
|
8
|
+
|
|
9
|
+
Prefer `DeckVoiceError` now; if later reused for trackpad/deck actions, lift the same shape to `LatsError`.
|
|
10
|
+
|
|
11
|
+
```swift
|
|
12
|
+
public struct DeckVoiceError: Codable, Equatable, Identifiable, Sendable {
|
|
13
|
+
public var id: String // uuid or request id
|
|
14
|
+
public var code: DeckVoiceErrorCode
|
|
15
|
+
public var severity: DeckErrorSeverity
|
|
16
|
+
public var recoverable: Bool
|
|
17
|
+
public var retry: DeckRetryHint?
|
|
18
|
+
public var source: DeckErrorSource // mac, ipad, vox, daemon, intent, bridge
|
|
19
|
+
public var owner: String? // e.g. "Vox", "Lattices", "Bridge"
|
|
20
|
+
public var message: String // cockpit copy, already human-readable
|
|
21
|
+
public var remediation: DeckRemediationAction?
|
|
22
|
+
public var occurredAt: Date
|
|
23
|
+
public var detail: String? // diagnostic-only
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public enum DeckVoiceErrorCode: String, Codable, Sendable { case vox_unreachable, daemon_unreachable, network, connection_lost, mic_denied, accessibility_denied, mic_busy, no_active_target, vox_not_running, vox_loading, intent_unresolved, action_failed, transcription_failed, empty_transcript, language_unsupported }
|
|
27
|
+
public enum DeckErrorSeverity: String, Codable, Sendable { case info, warning, error, blocked }
|
|
28
|
+
public enum DeckRetryHint: String, Codable, Sendable { case silent, immediate, afterLaunch, userAction }
|
|
29
|
+
public enum DeckErrorSource: String, Codable, Sendable { case mac, ipad, vox, daemon, intent, bridge }
|
|
30
|
+
public enum DeckRemediationAction: Codable, Equatable, Sendable {
|
|
31
|
+
case openVox, openSystemSettings(kind: String), retryVoice, openDiagnostics, chooseTarget
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Add `var error: DeckVoiceError?` and optionally `var lastError: DeckVoiceError?` to `DeckVoiceState`, preserving existing `phase`, transcript, and provider fields (`swift/Sources/DeckKit/DeckRuntimeSnapshot.swift:49-68`). Codes should stay stable string raw values for JSON logs and iPad bridge snapshots.
|
|
36
|
+
|
|
37
|
+
## Categories
|
|
38
|
+
|
|
39
|
+
| Category | Codes | Recovery rule |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Connection | `vox_unreachable`, `daemon_unreachable`, `network`, `connection_lost` | Recoverable unless active capture was lost. Silent reconnect when idle; visible banner during `listening`/`transcribing`. |
|
|
42
|
+
| Permission | `mic_denied`, `accessibility_denied` | Needs user action. `mic_denied` is Mac/Vox-owned; iPad only relays it. `accessibility_denied` blocks execution/navigation. |
|
|
43
|
+
| State | `mic_busy { owner }`, `no_active_target`, `vox_not_running`, `vox_loading` | Usually recoverable. `mic_busy` waits for owner; `vox_not_running` supports launch-on-demand. |
|
|
44
|
+
| Execution | `intent_unresolved`, `action_failed`, `transcription_failed` | Recoverable by retry or edited command; escalate to log if repeated. |
|
|
45
|
+
| Validation | `empty_transcript`, `language_unsupported` | Recoverable; no scary chrome. Treat as a missed command, not a crash. |
|
|
46
|
+
|
|
47
|
+
Copy examples: `Mic in use by Vox — finish memo first`, `No target window`, `Vox offline — starting`, `Connection lost — press again`, `Intent not found`.
|
|
48
|
+
|
|
49
|
+
## Presentation patterns
|
|
50
|
+
|
|
51
|
+
**Mac VoiceCommandWindow.** Keep the three-column cockpit. The top mic bar already owns live state (`connecting...`, `processing...`; `app/Sources/VoiceCommandWindow.swift:692-719`); render the active error as a compact red/amber status chip there. The center column uses `commandSection` cards (`app/Sources/VoiceCommandWindow.swift:1287-1304`): show a single `blocked`/`needs action` card only when the user can do something. The footer already has key chips (`app/Sources/VoiceCommandWindow.swift:1308-1348`); replace the generic command list with contextual remediation: `⌥ Retry`, `Return Open Vox`, `⌘, Permissions`. Logs stay in the right rail, using existing level colors (`app/Sources/VoiceCommandWindow.swift:1112-1150`).
|
|
52
|
+
|
|
53
|
+
**Mac HUD.** `HUDTopBar.voiceStatus` already has dot, label, transcript, response (`app/Sources/HUDTopBar.swift:134-198`). Add severity tint: green idle/listening, amber connecting/recoverable, red blocked. For active voice errors, HUD shows a one-line banner in the top bar; no sheet.
|
|
54
|
+
|
|
55
|
+
**iPad Home.** Add `HomeVoiceOverlay` as the full voice modal for active relay: title row `VOICE`, phase, transcript, Mac owner, and one remediation button. The bottom bar already has dense status slots and `hold·space` (`iOS/LatticesCompanion/Sources/Home/HomeBottomBar.swift:58-68`, `iOS/LatticesCompanion/Sources/Home/HomeBottomBar.swift:129-148`); render idle/recoverable errors inline there (`voice · reconnecting`, `voice · Vox offline`). Use a deck overlay banner only when an issued iPad action failed. Use sheets only for permissions/pairing because they need human action. This follows the chrome rule: do not remove noisy UI; replace it with state that answers “what am I controlling, who is listening, what failed?” (`/Users/arach/.claude/projects/-Users-arach-dev-lattices/memory/feedback_chrome_design.md:11-13`).
|
|
56
|
+
|
|
57
|
+
## Unhappy-path prescriptions
|
|
58
|
+
|
|
59
|
+
**Launch Vox on demand.** Spec flow is detect installed/not running, open Vox, show `Starting Vox...`, wait up to 10s, retry `startDictation`, then fail with manual-open copy (`docs/voice-command-protocol.md:73-89`). Current Mac waits 2s after `connect()` (`app/Sources/VoiceCommandWindow.swift:290-313`); design target is `vox_not_running` → `vox_loading` → retry → either clear error or `vox_unreachable` with `openVox`.
|
|
60
|
+
|
|
61
|
+
**Mic busy.** Preserve owner attribution from protocol (`docs/voice-command-protocol.md:127-135`). `mic_busy(owner: "Vox")` is warning, recoverable, retry hint `userAction`; message: `Mic in use by Vox — finish memo first`. If owner is unknown: `Mic busy — wait for current recording`.
|
|
62
|
+
|
|
63
|
+
**Connection recovery.** If idle, reconnect silently and write log only. If active, show red `Connection lost`; do not auto-retry captured audio because Vox cancels dropped sockets (`docs/voice-command-protocol.md:174-188`). iPad shows `Mac voice link lost` if bridge lost, not `network` unless the iPad transport failed.
|
|
64
|
+
|
|
65
|
+
**JSONL.** Add `~/.lattices/voice.jsonl` beside `lattices.log` (current log path is `~/.lattices/lattices.log`; `app/Sources/DiagnosticLog.swift:40-59`). Shape:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{"ts":"2026-04-27T14:03:11.120Z","platform":"mac","sessionId":"...","phase":"listening","event":"error","error":{"code":"mic_busy","severity":"warning","recoverable":true,"source":"vox","owner":"Vox","message":"Mic in use by Vox — finish memo first"},"transcript":null,"intent":null,"durationMs":820}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Cross-platform conventions
|
|
72
|
+
|
|
73
|
+
Tone: terse cockpit, no apologies. Prefer noun-state-action: `Vox offline — starting`, `No target — pick window`, `Access denied — enable Accessibility`. Tint maps to existing palettes: Mac `Palette.detach` amber and `Palette.kill` red (`app/Sources/Theme.swift:19-23`); iPad `LatsPalette.amber/red` (`iOS/LatticesCompanion/Sources/LatsDeckScreen.swift:19-25`). Icons: `mic.fill` live, `mic.slash` denied, `waveform.badge.exclamationmark` transcription, `bolt.trianglebadge.exclamationmark` execution, `wifi.exclamationmark` connection, `scope` target. Ownership: Mac owns Vox, mic, Accessibility, intent execution, and JSONL. iPad owns relay/bridge/network presentation and never claims direct mic capture.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lattices/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Agentic window manager for macOS — programmable workspace, smart layouts, managed tmux sessions, and a 35+-method agent API",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lattices": "./bin/lattices.ts",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"exports": {
|
|
24
24
|
".": "./bin/client.ts",
|
|
25
|
+
"./assistant-intelligence": "./bin/assistant-intelligence.ts",
|
|
25
26
|
"./daemon-client": "./bin/daemon-client.ts",
|
|
26
27
|
"./project-twin": "./bin/project-twin.ts"
|
|
27
28
|
},
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"@ai-sdk/openai": "^3.0.41",
|
|
56
57
|
"@ai-sdk/xai": "^3.0.67",
|
|
57
58
|
"@arach/speakeasy": "^0.2.8",
|
|
58
|
-
"ai": "^6.0.116"
|
|
59
|
+
"ai": "^6.0.116",
|
|
60
|
+
"zod": "^3.25.76"
|
|
59
61
|
}
|
|
60
62
|
}
|