@lasso-ai/cli 1.0.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.
- package/ARCHITECTURE.md +342 -0
- package/CHANGELOG.md +102 -0
- package/CODE_OF_CONDUCT.md +129 -0
- package/CONTRIBUTING.md +122 -0
- package/LICENSE +7 -0
- package/README.md +548 -0
- package/SECURITY.md +65 -0
- package/SUPPORT.md +31 -0
- package/dist/cli/agent.d.ts +61 -0
- package/dist/cli/agent.js +418 -0
- package/dist/cli/auth.d.ts +38 -0
- package/dist/cli/auth.js +162 -0
- package/dist/cli/bridge.d.ts +160 -0
- package/dist/cli/bridge.js +450 -0
- package/dist/cli/host/certificates.d.ts +12 -0
- package/dist/cli/host/certificates.js +52 -0
- package/dist/cli/host/client.d.ts +49 -0
- package/dist/cli/host/client.js +141 -0
- package/dist/cli/host/daemon.d.ts +50 -0
- package/dist/cli/host/daemon.js +368 -0
- package/dist/cli/host/dns.d.ts +80 -0
- package/dist/cli/host/dns.js +255 -0
- package/dist/cli/host/install.d.ts +32 -0
- package/dist/cli/host/install.js +177 -0
- package/dist/cli/host/next-host-entry.d.ts +1 -0
- package/dist/cli/host/next-host-entry.js +82 -0
- package/dist/cli/host/paths.d.ts +15 -0
- package/dist/cli/host/paths.js +55 -0
- package/dist/cli/host/registry.d.ts +31 -0
- package/dist/cli/host/registry.js +103 -0
- package/dist/cli/host/runtime.d.ts +23 -0
- package/dist/cli/host/runtime.js +134 -0
- package/dist/cli/host/vite-host-entry.d.ts +1 -0
- package/dist/cli/host/vite-host-entry.js +59 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +322 -0
- package/dist/cli/project.d.ts +56 -0
- package/dist/cli/project.js +298 -0
- package/dist/cli/server/next.d.ts +6 -0
- package/dist/cli/server/next.js +76 -0
- package/dist/cli/server/vite.d.ts +1 -0
- package/dist/cli/server/vite.js +51 -0
- package/dist/cli/utils/framework.d.ts +2 -0
- package/dist/cli/utils/framework.js +26 -0
- package/dist/overlay.js +20365 -0
- package/docs/PUBLISHING.md +63 -0
- package/package.json +106 -0
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
> Product name: **Lasso**.
|
|
4
|
+
|
|
5
|
+
## 1. Core principle
|
|
6
|
+
|
|
7
|
+
Lasso edits **source code**, never the live DOM. A visual selection is a pointer into a
|
|
8
|
+
codebase, not a target for direct manipulation. This decision shapes every component
|
|
9
|
+
below — it's what separates a real dev tool from a demo that only works on static HTML.
|
|
10
|
+
|
|
11
|
+
## 2. Repository layout
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
src/
|
|
15
|
+
cli/ # the Node CLI (the coordinator)
|
|
16
|
+
index.ts # entry point: `lasso` / `lasso dev`, framework detection dispatch, `daemon`/`projects`/`register`
|
|
17
|
+
project.ts # project identity: `lasso init` (writes `{id, domain}`), `lasso dev` session resolution
|
|
18
|
+
auth.ts # `lasso auth`: browser-OAuth login, credential store (~/.lasso/credentials.json), status, logout
|
|
19
|
+
bridge.ts # WebSocket bridge the overlay connects to
|
|
20
|
+
server/
|
|
21
|
+
vite.ts # Vite dev server with the source-mapping plugin injected in-memory
|
|
22
|
+
next.ts # Next.js dev server integration (React _debugSource)
|
|
23
|
+
utils/
|
|
24
|
+
framework.ts # framework/bundler detection
|
|
25
|
+
host/ # Lasso Host: user-level local domains + app hosting
|
|
26
|
+
paths.ts # host dir (~/.lasso/host), registry/pid/log paths, ports, the `.lasso` TLD
|
|
27
|
+
registry.ts # domain → {projectId, directory} persistence (atomic, 0600), unique-domain generation
|
|
28
|
+
runtime.ts # auto-start dev servers (Vite/Next), readiness polling, port picking
|
|
29
|
+
dns.ts # UDP responder (*.lasso → 127.0.0.1, NXDOMAIN outside) + per-OS resolver config
|
|
30
|
+
daemon.ts # the background host: HTTP+WS proxy, /_host/* control API, single-instance, crash guard
|
|
31
|
+
client.ts # CLI-side helpers: health, registry read/register, stop/restart
|
|
32
|
+
install.ts # `lasso daemon install/uninstall`, LaunchAgent, daemon spawn/status
|
|
33
|
+
vite-host-entry.js # programmatic Vite with `.lasso` allow-listed (Vite rejects unknown Host headers)
|
|
34
|
+
overlay/
|
|
35
|
+
index.ts # browser-side overlay (single file, bundled to dist/overlay.js)
|
|
36
|
+
# also hosts the realtime client: presence, locks, comments, voice
|
|
37
|
+
audio/
|
|
38
|
+
transcribe.ts # client-side audio capture (MediaRecorder) & STT relay
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Two artifacts ship from `pnpm build`:
|
|
42
|
+
|
|
43
|
+
- `dist/cli/index.js` — the CLI, compiled with `tsc`
|
|
44
|
+
- `dist/overlay.js` — the browser overlay, bundled with `esbuild`
|
|
45
|
+
|
|
46
|
+
## 3. System overview
|
|
47
|
+
|
|
48
|
+
Three parties, all coordinating around one shared filesystem:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
┌─────────────────────────────── Your machine ───────────────────────────────┐
|
|
52
|
+
│ │
|
|
53
|
+
│ Browser Local CLI │
|
|
54
|
+
│ ┌──────────────┐ selection ┌──────────────────┐ writes ┌───────┐ │
|
|
55
|
+
│ │ Overlay │──────────────▶│ Bridge │───────────▶│ Source │ │
|
|
56
|
+
│ │ (lasso, UI) │ + prompt │ Source resolver │ │ files │ │
|
|
57
|
+
│ │ Running app │◀──────────────│ Diff preview │ └───────┘ │
|
|
58
|
+
│ │ (Vite/Next │ diff/accept │ Agent adapter │ │ │
|
|
59
|
+
│ │ HMR) │ └────────┬──────────┘ │ │
|
|
60
|
+
│ └──────────────┘ │ dev server │
|
|
61
|
+
│ │ watches ↓ │
|
|
62
|
+
└────────────────────────────────────────────┼──────────────────────────────┘
|
|
63
|
+
│
|
|
64
|
+
┌──────────┴──────────┐
|
|
65
|
+
│ Coding agent │
|
|
66
|
+
│ (pluggable — see §6)│
|
|
67
|
+
└──────────────────────┘
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Everything except the coding agent call runs locally. Nothing is ever written to disk
|
|
71
|
+
without an explicit accept from the user. The agent is the only party that ever leaves the
|
|
72
|
+
machine, and only with the exact context the CLI assembled for it.
|
|
73
|
+
|
|
74
|
+
## 4. Browser layer (capture only)
|
|
75
|
+
|
|
76
|
+
Responsibilities, and _only_ these:
|
|
77
|
+
|
|
78
|
+
- Render the floating toolbar (idle / select-mode / selection-active states).
|
|
79
|
+
- Lasso or click select. Match elements by **center-point containment**, not bounding-box
|
|
80
|
+
overlap (overlap over-selects parents whose edge merely brushes the lasso rect).
|
|
81
|
+
- Resolve each selected DOM node to a `data-source` attribute (file, line, component name)
|
|
82
|
+
injected by the dev-time build plugin. Where no plugin is present, fall back to React's
|
|
83
|
+
`_debugSource` fiber data.
|
|
84
|
+
- Take a screenshot of the selection (`html2canvas`) — visual context measurably improves
|
|
85
|
+
edit quality even when the AI has the source.
|
|
86
|
+
- Show the inline prompt box anchored to the selection (never a blocking `prompt()`).
|
|
87
|
+
- Render the diff/accept/undo UI once the CLI streams a proposed change back.
|
|
88
|
+
- **Never mutate the DOM.** All visual changes the user sees post-edit come from the
|
|
89
|
+
framework's own HMR reload, not from this layer.
|
|
90
|
+
|
|
91
|
+
Transport: a persistent **WebSocket** to the local CLI (`src/cli/bridge.ts`), not one-shot
|
|
92
|
+
`fetch` calls — this lets the CLI push streaming diff previews and error states back
|
|
93
|
+
without polling.
|
|
94
|
+
|
|
95
|
+
## 5. Local CLI (the coordinator)
|
|
96
|
+
|
|
97
|
+
A Node process that wraps the user's existing dev server. Entry: `src/cli/index.ts`.
|
|
98
|
+
|
|
99
|
+
### 5.1 Responsibilities
|
|
100
|
+
|
|
101
|
+
1. Detect framework/bundler on `npx lasso` (`src/cli/utils/framework.ts` reads
|
|
102
|
+
`vite.config.*`, `next.config.*`, `package.json`).
|
|
103
|
+
2. Spawn the dev server programmatically with the source-mapping plugin injected in memory
|
|
104
|
+
(`src/cli/server/vite.ts`, `src/cli/server/next.ts`) — the user's own config files are
|
|
105
|
+
never touched on disk.
|
|
106
|
+
3. Host the WebSocket bridge (`src/cli/bridge.ts`) the browser overlay connects to.
|
|
107
|
+
4. On a selection + instruction: read the referenced source file(s), assemble context
|
|
108
|
+
(source snippet, imports, relevant CSS/Tailwind config, screenshot, instruction), and
|
|
109
|
+
hand it to the coding agent (§6).
|
|
110
|
+
5. Hold the returned diff in memory and stream it to the browser for preview — never write
|
|
111
|
+
on receipt.
|
|
112
|
+
6. On accept: snapshot the file's prior content (for undo), then apply the diff.
|
|
113
|
+
7. On undo: restore the snapshot, full stop — no re-generation needed, so retries are free.
|
|
114
|
+
|
|
115
|
+
### 5.2 Source resolution strategies
|
|
116
|
+
|
|
117
|
+
| Setup | Method |
|
|
118
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
119
|
+
| Vite (React/Vue/Svelte/Solid) | Native Vite plugin, spawned via `createServer()` — injects `data-source` attrs at transform time. No config file edits. |
|
|
120
|
+
| Next.js | React's `_debugSource` fiber data, read at runtime — no build plugin needed, slightly less precise (nearest component boundary, not exact JSX line). |
|
|
121
|
+
| Webpack-only / CRA / Angular | **Not supported in v1.** The CLI should say so explicitly rather than fail silently. |
|
|
122
|
+
|
|
123
|
+
### 5.3 Diff format
|
|
124
|
+
|
|
125
|
+
The agent returns **old-string/new-string pairs**, not a full-file rewrite. Full-file
|
|
126
|
+
regeneration risks silently dropping code the model wasn't told about; a targeted
|
|
127
|
+
find-and-replace is deterministic and safe to apply mechanically.
|
|
128
|
+
|
|
129
|
+
### 5.4 Multi-instance handling
|
|
130
|
+
|
|
131
|
+
Editing a component's source file affects every rendered instance, since the source is
|
|
132
|
+
shared. This is usually correct, but the UI should say so explicitly at accept-time
|
|
133
|
+
("this edits the component template — affects N instances on this page") so it never feels
|
|
134
|
+
like the tool did something unexpected.
|
|
135
|
+
|
|
136
|
+
## 6. Coding agent — pluggable, not hardcoded
|
|
137
|
+
|
|
138
|
+
Lasso ships its own default agent, but the CLI's job is to assemble _context_, not to be
|
|
139
|
+
married to one model.
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
context (source + screenshot + instruction)
|
|
143
|
+
│
|
|
144
|
+
▼
|
|
145
|
+
┌───────────────┐
|
|
146
|
+
│ Agent adapter │ interface: given context, return old/new string pairs
|
|
147
|
+
└───────┬───────┘
|
|
148
|
+
│
|
|
149
|
+
┌──────┼───────────────────┬─────────────────────┐
|
|
150
|
+
▼ ▼ ▼ ▼
|
|
151
|
+
Built-in Claude Code User's own CLI coding Any future
|
|
152
|
+
agent (headless/ agent (Cursor CLI, adapter
|
|
153
|
+
(default) `claude -p`) Aider, etc.)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- **Built-in agent** (`agent: "builtin"`): default path, zero setup, calls a hosted model
|
|
157
|
+
directly (`@anthropic-ai/sdk`) with the assembled context and the old/new-string contract
|
|
158
|
+
from §5.3.
|
|
159
|
+
- **Claude Code passthrough** (`agent: "claude-code"`): the CLI shells out to Claude Code
|
|
160
|
+
in headless/print mode (`claude -p`), passing the assembled context as the prompt and
|
|
161
|
+
parsing its file edits back into the same diff-preview pipeline. This lets a user keep
|
|
162
|
+
using their existing Claude Code setup (subscription, project memory, MCP tools) while
|
|
163
|
+
still getting the point-and-select UX.
|
|
164
|
+
- **Bring-your-own-agent** (`agent: "custom"`): define the adapter interface once (context
|
|
165
|
+
in, old/new-string pairs out) and let power users wire in whatever CLI coding tool they
|
|
166
|
+
already trust. Lasso's value in this mode is entirely the capture + context-assembly
|
|
167
|
+
pipeline (§4–5), not the model itself.
|
|
168
|
+
|
|
169
|
+
Selection is a config choice, not an either/or product decision:
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
// lasso.config.json (before `lasso init`)
|
|
173
|
+
{
|
|
174
|
+
"agent": "builtin" // | "claude-code" | "custom"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// lasso.config.json (after `lasso init` — id is the only project field)
|
|
178
|
+
{
|
|
179
|
+
"agent": "builtin",
|
|
180
|
+
"id": "proj_3f2a9c…" // workspace-scoped; commit it so teammates share the session
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 7. Realtime collaboration (optional)
|
|
185
|
+
|
|
186
|
+
The overlay also speaks to `collab-server` (a Socket.IO server in the monorepo) so
|
|
187
|
+
teammates can collaborate on the same running app. Identity is split across two
|
|
188
|
+
credentials: the **API key** (`lss_live_…` — who you are + which workspace) and
|
|
189
|
+
the **project id** (which Lasso project you're opening). The API key comes from
|
|
190
|
+
`LASSO_API_KEY`, or — after `lasso auth login` — from `~/.lasso/credentials.json`.
|
|
191
|
+
Startup flows:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
0) lasso auth login (once per machine, device-style OAuth)
|
|
195
|
+
│ auth.ts POSTs /auth/cli/start → prints + opens the verification URL
|
|
196
|
+
│ (web /oauth/continue/cli?code=…, cookie auth) → /auth/cli/confirm mints an API key
|
|
197
|
+
│ in the user's first ACTIVE workspace; auth.ts polls /auth/cli/status
|
|
198
|
+
▼
|
|
199
|
+
the key is delivered exactly once and stored at ~/.lasso/credentials.json (0600)
|
|
200
|
+
|
|
201
|
+
1) lasso init (once per repo, API-key auth)
|
|
202
|
+
│ project.ts POSTs the app manifest to /collab/projects/register
|
|
203
|
+
▼
|
|
204
|
+
collab-server hashes the key → api_keys → derives the workspace → creates or
|
|
205
|
+
reuses the project there (idempotent by git remote/name). CLI writes
|
|
206
|
+
lasso.config.json = { "id": "proj_…" }. Key never touches disk.
|
|
207
|
+
|
|
208
|
+
2) lasso dev (every run, API-key auth)
|
|
209
|
+
│ reads lasso.config.json, POSTs /collab/projects/:projectId/session
|
|
210
|
+
▼
|
|
211
|
+
collab-server resolves key → workspace, verifies the project belongs to it
|
|
212
|
+
(else 403 → realtime disabled, local editing continues), authenticates the
|
|
213
|
+
session (uid === projectId).
|
|
214
|
+
▼ bridge sends { collab: { projectId, realtimeUrl, name, workspaceId } } with `config`
|
|
215
|
+
▼
|
|
216
|
+
overlay io(realtimeUrl) → session:join { sessionId: projectId }
|
|
217
|
+
◀ session joins are gated: the browser user must own the session's workspace
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Element identity
|
|
221
|
+
|
|
222
|
+
Cross-user locks, comments, and spotlight key off a deterministic `elementKey`:
|
|
223
|
+
|
|
224
|
+
1. `data-source` / `data-lasso-source` attribute (best — from the build plugin) → `attr:…`
|
|
225
|
+
2. element `id` → `id:…`
|
|
226
|
+
3. stable CSS path (an `nth-child` chain on the ancestors) → `css:…`
|
|
227
|
+
|
|
228
|
+
This is **not** the random per-click `selectionId`. Two browsers looking at the same
|
|
229
|
+
app derive the same key, so a lock acquired on "the hero heading" in one tab is visible
|
|
230
|
+
and enforceable in the other. The overlay keeps an `elementRegistry` mapping key → local
|
|
231
|
+
Element to re-highlight remote selections.
|
|
232
|
+
|
|
233
|
+
### Flow pieces
|
|
234
|
+
|
|
235
|
+
- **Presence**: every joined socket emits `presence:update` (≈ every 30 s) with
|
|
236
|
+
`selection: { elementId, label, sourceHint }`; the server broadcasts
|
|
237
|
+
`presence:changed` snapshots. Only the selected element is synced (not raw
|
|
238
|
+
coordinates), which keeps the wire tiny and the boxes meaningful.
|
|
239
|
+
- **Lock mode**: before running an agent edit, the overlay `lock:acquire`s the
|
|
240
|
+
element. A `ok:false reason:"LOCKED"` ack means a teammate owns it → the edit is
|
|
241
|
+
blocked and a chip shows who. The lock is released when the edit is applied or
|
|
242
|
+
undone, and the client extends its held lock on the heartbeat.
|
|
243
|
+
- **Comments**: `comments:add` with `elementId` + `meta` (source hint, label,
|
|
244
|
+
position); the panel can filter to the current element or the whole session.
|
|
245
|
+
Replies nest under a root comment via `parentId`.
|
|
246
|
+
- **Spotlight**: clicking a presence avatar emits `collab:spotlight`; every tab
|
|
247
|
+
highlights the element (or the sender's own highlight) for ~2.6 s with a
|
|
248
|
+
"name → element" chip.
|
|
249
|
+
- **Voice**: P2P WebRTC mesh. `voice:join` returns existing peers; the newcomer
|
|
250
|
+
creates a peer connection per peer and offers; existing members answer. Media
|
|
251
|
+
never touches the server. Muting is a right-click on the (live) voice button.
|
|
252
|
+
|
|
253
|
+
Auth uses the app's own auth cookie (`withCredentials: true`) with `auth: { token }`
|
|
254
|
+
read from `document.cookie` as a fallback. That works on `localhost` because
|
|
255
|
+
cookie-origin and realtime-server-origin are same-site; production deployments keep
|
|
256
|
+
both on the same registrable domain (documented in the collab-server README).
|
|
257
|
+
|
|
258
|
+
## 8. Lasso Host (local domains + app hosting)
|
|
259
|
+
|
|
260
|
+
Lasso Host turns every project into a first-class local URL. `lasso init` now also
|
|
261
|
+
generates a stable unique domain for the project (`{ "id": "proj_…", "domain": "…" }`),
|
|
262
|
+
so `http://app.lasso` maps to that project — no remembering ports, no manual
|
|
263
|
+
`npm run dev`.
|
|
264
|
+
|
|
265
|
+
- **Daemon**: `lasso daemon` starts a single-instance background process
|
|
266
|
+
(pid-guarded by holding the proxy port; extra invocations fail with
|
|
267
|
+
"already running"). Control endpoints under `/_host/*` (health, registry,
|
|
268
|
+
register, unregister, stop, restart). Logs to `~/.lasso/host/daemon.log`.
|
|
269
|
+
- **Proxy**: binds `127.0.0.1` only. Any request with a `*.lasso` Host header is
|
|
270
|
+
resolved through the registry and reverse-proxied to that project's dev server;
|
|
271
|
+
non-`.lasso` hosts get a 404, so nothing outside the namespace is served.
|
|
272
|
+
WebSocket upgrades (HMR) pass through the same path.
|
|
273
|
+
- **Auto-start**: a request to a stopped project spawns its dev server and waits
|
|
274
|
+
for readiness before proxying. Vite is launched programmatically
|
|
275
|
+
(`vite-host-entry.js`) with `*.lasso` allow-listed because Vite rejects unknown
|
|
276
|
+
Host headers; Next runs via `next dev --port`. Unknown frameworks report a clear
|
|
277
|
+
error rather than blindly running `npm run dev`. A crash guard stops restarts
|
|
278
|
+
after repeated immediate crashes.
|
|
279
|
+
- **DNS**: `*.lasso` resolves to `127.0.0.1` via a tiny UDP responder (A record;
|
|
280
|
+
NXDOMAIN outside the namespace). Platform config behind a `DomainResolver`
|
|
281
|
+
interface: macOS `/etc/resolver/lasso` (the only `sudo` step; the responder's
|
|
282
|
+
port is otherwise unprivileged), Linux systemd-resolved split-DNS, and Windows
|
|
283
|
+
hosts entries. The HTTP proxy runs on port 6766 and the HTTPS proxy on 6767,
|
|
284
|
+
so registered URLs are shown as `http://app.lasso:6766` unless DNS is installed.
|
|
285
|
+
- **Registry**: `~/.lasso/host/registry.json` (atomic write, `0600`) maps
|
|
286
|
+
domain → `{ projectId, directory, registeredAt }`. `lasso register` reuses an
|
|
287
|
+
existing registration for the same directory, never duplicates, and migrates
|
|
288
|
+
the old domain when a new one is given (also rewriting `lasso.config.json`).
|
|
289
|
+
- **Trust**: no API keys or source paths in project config; only registered
|
|
290
|
+
domains proxy; the daemon listens on loopback by default.
|
|
291
|
+
|
|
292
|
+
## 9. Speech-to-Text & Voice Input Architecture
|
|
293
|
+
|
|
294
|
+
Lasso supports natural voice prompting in the prompt toolbar and voice dictation in component comment pins without requiring manual audio file management.
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
298
|
+
│ Browser Overlay │
|
|
299
|
+
│ - MediaRecorder captures audio (WebM/Opus / WAV) │
|
|
300
|
+
│ - Reactive mic animation (.recording / .transcribing) │
|
|
301
|
+
│ - Base64 payload packaging │
|
|
302
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
303
|
+
│
|
|
304
|
+
┌──────────────┴──────────────┐
|
|
305
|
+
│ Bridge WebSocket or Fetch │
|
|
306
|
+
└──────────────┬──────────────┘
|
|
307
|
+
▼
|
|
308
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
309
|
+
│ Lasso Server /api/v1/transcribe (STTService) │
|
|
310
|
+
│ │
|
|
311
|
+
│ 1. Attempt Gradium ASR (POST api.gradium.ai/speech/asr) │
|
|
312
|
+
│ - Fast streaming NDJSON transcription │
|
|
313
|
+
│ - Credit check (402, 429, error signals) │
|
|
314
|
+
│ │
|
|
315
|
+
│ 2. Automatic Fallback to Deepgram (Nova-2) │
|
|
316
|
+
│ - Seamless failover if Gradium credits finish/fail │
|
|
317
|
+
│ - 15-minute cooldown before retrying Gradium │
|
|
318
|
+
└─────────────────────────────────────────────────────────────┘
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
1. **Client Capture**: `src/overlay/audio/transcribe.ts` starts an audio stream via `navigator.mediaDevices.getUserMedia({ audio: true })`. Chunks are gathered into a single blob on stop.
|
|
322
|
+
2. **Transport**: The client transmits base64-encoded audio either over the local CLI bridge socket (`{ type: "transcribe" }`) or directly to the server REST API (`POST /api/v1/transcribe`), avoiding cross-origin complexities.
|
|
323
|
+
3. **Provider Pooling**: The backend `sttService` attempts Gradium first. If Gradium responds with a credit exhaustion code (402, 429, or out-of-credit status), it transparently falls back to Deepgram Nova-2 and returns the transcribed text to the client.
|
|
324
|
+
|
|
325
|
+
## 10. Open questions for v1
|
|
326
|
+
|
|
327
|
+
- Exact context window budget per request (full file vs. just the referenced function).
|
|
328
|
+
- Whether the diff-preview UI lives in the browser overlay only, or also as a terminal
|
|
329
|
+
side panel for the CLI.
|
|
330
|
+
- Rate limiting / cost guardrails when using a hosted default agent vs. a user's own
|
|
331
|
+
Claude Code subscription.
|
|
332
|
+
- Extending source resolution beyond Vite and Next.js (Webpack/CRA/Angular).
|
|
333
|
+
|
|
334
|
+
## 11. Trust model
|
|
335
|
+
|
|
336
|
+
- **Telemetry-free by default.** Nothing about a user's source code leaves their machine
|
|
337
|
+
except what's explicitly sent to whichever agent they've configured.
|
|
338
|
+
- **No writes without accept.** Diffs live in memory until the user confirms; undo restores
|
|
339
|
+
a pre-edit snapshot.
|
|
340
|
+
- **Configs are never modified.** Build plugins are injected in memory via the CLI.
|
|
341
|
+
|
|
342
|
+
See `SECURITY.md` for how to report anything that breaks this model.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Open-source documentation: `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`,
|
|
13
|
+
`SECURITY.md`, `SUPPORT.md`, `LICENSE` (ISC), and this changelog.
|
|
14
|
+
- **Lasso Host** (`src/cli/host/`) — a user-level local domain server + runtime
|
|
15
|
+
that serves registered projects through `*.lasso` domains. New commands:
|
|
16
|
+
- `lasso daemon [start|status|stop|restart|install|uninstall]` — background
|
|
17
|
+
single-instance daemon (reverse HTTP **and WebSocket/HMR proxy**), persistent
|
|
18
|
+
project registry at `~/.lasso/host/registry.json`, always-bound `127.0.0.1`.
|
|
19
|
+
`install` adds a macOS LaunchAgent (auto-start at login) and configures the
|
|
20
|
+
local DNS resolver (`/etc/resolver/lasso` via `sudo`); `uninstall` reverses it.
|
|
21
|
+
- `lasso register [domain]` — register the current project under a `.lasso`
|
|
22
|
+
domain (or reuse/generate one), syncs `lasso.config.json`, and replaces the
|
|
23
|
+
previous domain when it changes. Re-registering never creates duplicates.
|
|
24
|
+
- `lasso projects` — list registered domains with running/stopped state.
|
|
25
|
+
- `lasso init` now also generates a unique local domain (derived from the
|
|
26
|
+
project directory name), registers it with Lasso Host, and writes
|
|
27
|
+
`{ "id": "proj_…", "domain": "app.lasso" }`.
|
|
28
|
+
- Auto-start on traffic: a request to a stopped project starts its dev server
|
|
29
|
+
(Vite launched programmatically with `.lasso` allow-listed, Next dev via
|
|
30
|
+
`next dev --port`), waits for readiness, then proxies — no manual
|
|
31
|
+
`npm run dev`. Crashing projects are guarded (no runaway restarts).
|
|
32
|
+
- DNS: a tiny UDP responder answers `*.lasso → 127.0.0.1` (NXDOMAIN outside
|
|
33
|
+
the namespace); the platform resolver abstraction covers macOS
|
|
34
|
+
(`/etc/resolver/lasso`), Linux (systemd-resolved split-DNS), and Windows
|
|
35
|
+
(per-domain hosts entries, best-effort). No API keys or arbitrary paths are
|
|
36
|
+
exposed — only registered domains are proxied.
|
|
37
|
+
- **`lasso auth` command group**: `lasso auth login` (browser OAuth — the CLI
|
|
38
|
+
prints/opens a verification URL, the logged-in dashboard user confirms, and the
|
|
39
|
+
CLI stores the minted API key in `~/.lasso/credentials.json` at `0600`),
|
|
40
|
+
`lasso auth status` (who's signed in + workspace + masked key), and
|
|
41
|
+
`lasso auth logout`. All credits feed `init`/`dev` automatically; `LASSO_API_KEY`
|
|
42
|
+
still overrides the stored credential.
|
|
43
|
+
- **`lasso init`**: registers the app with your Lasso workspace (API-key
|
|
44
|
+
authenticated) and writes `lasso.config.json` containing only the project id
|
|
45
|
+
(`{ "id": "proj_…" }`). Idempotent — re-running reuses the id; commit the file
|
|
46
|
+
so teammates share the same project. The API key is **not** stored in config.
|
|
47
|
+
- **`lasso dev` project session**: reads `lasso.config.json`, authenticates with
|
|
48
|
+
the API key (`LASSO_API_KEY` env / prompt), lets the realtime server resolve
|
|
49
|
+
the key → workspace → project and authenticate the project session. Renders
|
|
50
|
+
realtime collaboration unavailable (local editing unaffected) when there is no
|
|
51
|
+
config, no key, or the project belongs to another workspace.
|
|
52
|
+
- **Realtime collaboration in the overlay**: presence avatars with online/away
|
|
53
|
+
dots, click-an-avatar spotlight, remote selection rings, live teammate cursors
|
|
54
|
+
with custom user colors and name badges, and a live activity strip.
|
|
55
|
+
- **Live multiplayer cursors**: broadcast cursor movement via Socket.IO presence,
|
|
56
|
+
rendering smoothed remote pointers for teammates in real time.
|
|
57
|
+
- **Component lock mode in the UI**: taking a suggestion acquires a lock on the
|
|
58
|
+
selected element; teammates see a refined "Locked by …" badge and the edit is
|
|
59
|
+
blocked until release or expiry.
|
|
60
|
+
- **Speech-to-Text (STT) voice input & dictation**:
|
|
61
|
+
- Interactive microphone button in the prompt card with animated listening and
|
|
62
|
+
transcribing states.
|
|
63
|
+
- Voice dictation button in the comment compose bar.
|
|
64
|
+
- Client-side audio recording module (`src/overlay/audio/transcribe.ts`) using
|
|
65
|
+
the `MediaRecorder` API.
|
|
66
|
+
- Multi-provider pooling via the backend server: primary transcription via
|
|
67
|
+
Gradium (`api.gradium.ai`), with automatic failover to Deepgram (`api.deepgram.com`)
|
|
68
|
+
when credits finish or errors occur.
|
|
69
|
+
- CLI bridge support for local `transcribe` and `transcribe_result` relay.
|
|
70
|
+
- **Comments panel**: thread comments anchored to the selected element (or whole
|
|
71
|
+
session), reply/resolve/reopen/delete, attachments, GIFs, and voice dictation.
|
|
72
|
+
- **Clipboard & Snippets panel**: manage, copy, and share frequently used code
|
|
73
|
+
snippets, design tokens, and references with private and shared tabs.
|
|
74
|
+
- **Voice chat**: P2P WebRTC mesh — join from the toolbar, mute with a right-click
|
|
75
|
+
while live.
|
|
76
|
+
- CLI → overlay `config` message carries `collab: { projectId, realtimeUrl,
|
|
77
|
+
name, version, workspaceId }` so the overlay can join the right (workspace-
|
|
78
|
+
gated) session. The bridge only forwards a config it successfully authenticated.
|
|
79
|
+
|
|
80
|
+
## [0.1.0] - 2026-09-21
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- `lasso` CLI with `dev` command (default). Detects Vite or Next.js and starts the
|
|
85
|
+
dev server with the Lasso overlay attached.
|
|
86
|
+
- Browser overlay: floating toolbar, select mode (click or lasso), center-point
|
|
87
|
+
element matching, inline prompt box, diff preview with accept/undo.
|
|
88
|
+
- WebSocket bridge (`startBridge`) connecting the overlay to the local CLI.
|
|
89
|
+
- Source mapping: Vite build plugin (`data-source` attributes, exact JSX lines);
|
|
90
|
+
Next.js via React `_debugSource` fiber data.
|
|
91
|
+
- Pluggable agent adapters: `builtin` (Anthropic), `claude-code` (headless
|
|
92
|
+
passthrough), and `custom` — selectable via `lasso.config.json`.
|
|
93
|
+
- In-memory diff contract: old-string/new-string pairs, no disk writes until accept.
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
|
|
97
|
+
- Nothing yet — 0.1.0 is the initial release of the working-name Lasso.
|
|
98
|
+
|
|
99
|
+
### Notes
|
|
100
|
+
|
|
101
|
+
- Version 0.1.0 was developed as an internal prototype. This changelog records
|
|
102
|
+
behavior from that point forward. The project uses the product name **Lasso**.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the
|
|
26
|
+
overall community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or
|
|
31
|
+
advances of any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email
|
|
35
|
+
address, without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement at
|
|
63
|
+
[security@example.com](mailto:security@example.com).
|
|
64
|
+
|
|
65
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
66
|
+
|
|
67
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
68
|
+
reporter of any incident.
|
|
69
|
+
|
|
70
|
+
## Enforcement Guidelines
|
|
71
|
+
|
|
72
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
73
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
74
|
+
|
|
75
|
+
### 1. Correction
|
|
76
|
+
|
|
77
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
78
|
+
unprofessional or unwelcome in the community.
|
|
79
|
+
|
|
80
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
81
|
+
clarity around the nature of the violation and an explanation of why the
|
|
82
|
+
behavior was inappropriate. A public apology may be requested.
|
|
83
|
+
|
|
84
|
+
### 2. Warning
|
|
85
|
+
|
|
86
|
+
**Community Impact**: A violation through a single incident or series of
|
|
87
|
+
actions.
|
|
88
|
+
|
|
89
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
90
|
+
interaction with the people involved, including unsolicited interaction with
|
|
91
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
92
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
93
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
|
94
|
+
ban.
|
|
95
|
+
|
|
96
|
+
### 3. Temporary Ban
|
|
97
|
+
|
|
98
|
+
**Community Impact**: A serious violation of community standards, including
|
|
99
|
+
sustained inappropriate behavior.
|
|
100
|
+
|
|
101
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
102
|
+
communication with the community for a specified period of time. No public or
|
|
103
|
+
private interaction with the people involved, including unsolicited interaction
|
|
104
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
105
|
+
Violating these terms may lead to a permanent ban.
|
|
106
|
+
|
|
107
|
+
### 4. Permanent Ban
|
|
108
|
+
|
|
109
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
110
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
111
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
112
|
+
|
|
113
|
+
**Consequence**: A permanent ban from any sort of public interaction within
|
|
114
|
+
the community.
|
|
115
|
+
|
|
116
|
+
## Attribution
|
|
117
|
+
|
|
118
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
119
|
+
version 2.1, available at
|
|
120
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
121
|
+
|
|
122
|
+
Community Impact Guidelines were inspired by
|
|
123
|
+
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
|
124
|
+
|
|
125
|
+
[homepage]: https://www.contributor-covenant.org
|
|
126
|
+
|
|
127
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
128
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
|
129
|
+
https://www.contributor-covenant.org/translations.
|