lattice-talk 0.1.4 → 0.1.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 +10 -2
- package/dist/index.js +39 -20
- package/dist/index.js.map +1 -1
- package/dist/tui/main.js +238 -130
- package/dist/tui/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,17 +90,25 @@ Run `lattice-talk bridge gemini` to spawn a Gemini agent into your configured wo
|
|
|
90
90
|
| Codex | `codex app-server` — injects into an in-flight turn via `turn/steer` |
|
|
91
91
|
| Windsurf | Not supported — Windsurf has no public programmatic session API |
|
|
92
92
|
|
|
93
|
-
Two things to know about the bridge: the harness CLI must be installed and logged in on the machine running the bridge, and bridged sessions auto-approve tool permissions so the agent can work unattended — run it with the same trust you'd give a `--dangerously-skip-permissions` session.
|
|
93
|
+
Two things to know about the bridge: the harness CLI must be installed and logged in on the machine running the bridge (for Claude the bridge downloads the `claude-code-acp` adapter via `npx` on first run), and bridged sessions auto-approve tool permissions so the agent can work unattended — run it with the same trust you'd give a `--dangerously-skip-permissions` session.
|
|
94
94
|
|
|
95
95
|
**Windsurf** stays on the MCP path: `mcp add windsurf` gives its agents `pull_messages` with `wait_ms`, which still wakes them the instant a message is published — it just requires the agent to ask.
|
|
96
96
|
|
|
97
|
+
### Which delivery should I use?
|
|
98
|
+
|
|
99
|
+
- **`mcp add`** — every harness, any agent you run yourself. Near-instant delivery via wake-up polling.
|
|
100
|
+
- **`bridge`** — when you want an agent that receives messages *without asking*, e.g. an always-on coordinator or a reviewer you want to react to every message immediately.
|
|
101
|
+
|
|
102
|
+
Both can run side by side on the same workspace.
|
|
103
|
+
|
|
97
104
|
## Requirements
|
|
98
105
|
|
|
99
106
|
| Requirement | Needed for |
|
|
100
107
|
| --- | --- |
|
|
101
|
-
| Node.js 20+ | The MCP server (`serve`)
|
|
108
|
+
| Node.js 20+ | The MCP server (`serve`) and the bridge |
|
|
102
109
|
| Redis | Sharing messages between agent processes — local, Docker, remote, or managed |
|
|
103
110
|
| Bun, or Node.js 26.4+ | The interactive dashboard (OpenTUI renders via native FFI) |
|
|
111
|
+
| The harness CLI (`claude`, `codex`, `gemini`, or `agent`) | `lattice-talk bridge` for that harness — installed and logged in |
|
|
104
112
|
|
|
105
113
|
The dashboard auto-detects a compatible runtime and tells you clearly if none is found. The MCP server itself needs only plain Node 20+.
|
|
106
114
|
|
package/dist/index.js
CHANGED
|
@@ -21086,7 +21086,7 @@ init_esm_shims();
|
|
|
21086
21086
|
// package.json
|
|
21087
21087
|
var package_default = {
|
|
21088
21088
|
name: "lattice-talk",
|
|
21089
|
-
version: "0.1.
|
|
21089
|
+
version: "0.1.5",
|
|
21090
21090
|
description: "Lattice \u2014 Cross-Harness MCP Session Bus. Shared sessions, DMs, rooms, memory, and OpenTelemetry for agents across Claude Code, Cursor, Codex, and custom harnesses.",
|
|
21091
21091
|
type: "module",
|
|
21092
21092
|
main: "./dist/index.js",
|
|
@@ -22442,11 +22442,17 @@ var NdjsonRpc = class {
|
|
|
22442
22442
|
const errRl = createInterface({ input: this.proc.stderr });
|
|
22443
22443
|
errRl.on("line", (line) => opts.onStderr(line));
|
|
22444
22444
|
}
|
|
22445
|
-
|
|
22445
|
+
const failAll = (err2) => {
|
|
22446
22446
|
this.closed = true;
|
|
22447
|
-
const err2 = new Error(`process exited with code ${code}`);
|
|
22448
22447
|
for (const p of this.pending.values()) p.reject(err2);
|
|
22449
22448
|
this.pending.clear();
|
|
22449
|
+
};
|
|
22450
|
+
this.proc.on("error", (e) => {
|
|
22451
|
+
failAll(e);
|
|
22452
|
+
opts.onExit?.(null);
|
|
22453
|
+
});
|
|
22454
|
+
this.proc.on("exit", (code) => {
|
|
22455
|
+
failAll(new Error(`process exited with code ${code}`));
|
|
22450
22456
|
opts.onExit?.(code);
|
|
22451
22457
|
});
|
|
22452
22458
|
}
|
|
@@ -22579,7 +22585,10 @@ var AcpDriver = class {
|
|
|
22579
22585
|
env: opts.env,
|
|
22580
22586
|
shell: this.shell,
|
|
22581
22587
|
onStderr: (line) => onEvent(`[${this.id}] ${line}`),
|
|
22582
|
-
onExit: (code) =>
|
|
22588
|
+
onExit: (code) => {
|
|
22589
|
+
onEvent(`[${this.id}] exited (code ${code ?? "?"})`);
|
|
22590
|
+
opts.onExit?.(code);
|
|
22591
|
+
}
|
|
22583
22592
|
});
|
|
22584
22593
|
this.rpc = rpc;
|
|
22585
22594
|
rpc.onRequest("session/request_permission", (params) => {
|
|
@@ -22609,15 +22618,16 @@ var AcpDriver = class {
|
|
|
22609
22618
|
if (text) onEvent(`[${this.id}] ${text}`);
|
|
22610
22619
|
}
|
|
22611
22620
|
});
|
|
22612
|
-
|
|
22613
|
-
protocolVersion: ACP_PROTOCOL_VERSION,
|
|
22614
|
-
clientCapabilities: {
|
|
22615
|
-
fs: { readTextFile: false, writeTextFile: false },
|
|
22616
|
-
terminal: false
|
|
22617
|
-
},
|
|
22618
|
-
clientInfo: { name: "lattice-talk-bridge", version: "0" }
|
|
22619
|
-
});
|
|
22621
|
+
let init;
|
|
22620
22622
|
try {
|
|
22623
|
+
init = await rpc.request("initialize", {
|
|
22624
|
+
protocolVersion: ACP_PROTOCOL_VERSION,
|
|
22625
|
+
clientCapabilities: {
|
|
22626
|
+
fs: { readTextFile: false, writeTextFile: false },
|
|
22627
|
+
terminal: false
|
|
22628
|
+
},
|
|
22629
|
+
clientInfo: { name: "lattice-talk-bridge", version: "0" }
|
|
22630
|
+
});
|
|
22621
22631
|
const res = await rpc.request("session/new", {
|
|
22622
22632
|
cwd: opts.cwd,
|
|
22623
22633
|
mcpServers: opts.mcpServers.map(serializeMcpServer)
|
|
@@ -22685,7 +22695,10 @@ var CodexDriver = class {
|
|
|
22685
22695
|
env: opts.env,
|
|
22686
22696
|
shell: this.shell,
|
|
22687
22697
|
onStderr: (line) => onEvent(`[codex] ${line}`),
|
|
22688
|
-
onExit: (code) =>
|
|
22698
|
+
onExit: (code) => {
|
|
22699
|
+
onEvent(`[codex] exited (code ${code ?? "?"})`);
|
|
22700
|
+
opts.onExit?.(code);
|
|
22701
|
+
}
|
|
22689
22702
|
});
|
|
22690
22703
|
this.rpc = rpc;
|
|
22691
22704
|
rpc.onNotification("turn/started", (params) => {
|
|
@@ -22899,7 +22912,11 @@ async function runBridge(opts) {
|
|
|
22899
22912
|
suggestedAgentId: opts.agentId,
|
|
22900
22913
|
tokenProtected: Boolean(opts.conn.joinToken)
|
|
22901
22914
|
}),
|
|
22902
|
-
onEvent: log2
|
|
22915
|
+
onEvent: log2,
|
|
22916
|
+
onExit: (code) => {
|
|
22917
|
+
log2(`[bridge] agent process exited (code ${code ?? "?"}) \u2014 shutting down.`);
|
|
22918
|
+
stop.abort();
|
|
22919
|
+
}
|
|
22903
22920
|
});
|
|
22904
22921
|
log2(`[bridge] ${opts.harness} session up \u2014 injecting room "${roomId}" traffic into it.`);
|
|
22905
22922
|
if (bridgedAgentId) {
|
|
@@ -22922,13 +22939,15 @@ async function runBridge(opts) {
|
|
|
22922
22939
|
}
|
|
22923
22940
|
}
|
|
22924
22941
|
);
|
|
22942
|
+
await sweep();
|
|
22925
22943
|
const sweepTimer = setInterval(() => void sweep(), SWEEP_MS);
|
|
22926
|
-
const discoveryTimer = setTimeout(
|
|
22927
|
-
()
|
|
22928
|
-
|
|
22929
|
-
|
|
22930
|
-
|
|
22931
|
-
|
|
22944
|
+
const discoveryTimer = setTimeout(() => {
|
|
22945
|
+
if (!bridgedAgentId) {
|
|
22946
|
+
log2(
|
|
22947
|
+
"[bridge] still waiting for the agent to join the workspace \u2014 check that it ran join_session."
|
|
22948
|
+
);
|
|
22949
|
+
}
|
|
22950
|
+
}, DISCOVERY_TIMEOUT_MS);
|
|
22932
22951
|
const onSignal = () => stop.abort();
|
|
22933
22952
|
process.on("SIGINT", onSignal);
|
|
22934
22953
|
process.on("SIGTERM", onSignal);
|