@geohar/unbien-cli 0.1.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/README.md +72 -0
- package/dist/client.d.ts +89 -0
- package/dist/client.js +210 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.d.ts +59 -0
- package/dist/commands.js +273 -0
- package/dist/commands.js.map +1 -0
- package/dist/connect.d.ts +2 -0
- package/dist/connect.js +475 -0
- package/dist/connect.js.map +1 -0
- package/dist/identity.d.ts +2 -0
- package/dist/identity.js +30 -0
- package/dist/identity.js.map +1 -0
- package/dist/invite.d.ts +10 -0
- package/dist/invite.js +28 -0
- package/dist/invite.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.js +20 -0
- package/dist/main.js.map +1 -0
- package/dist/panels.d.ts +40 -0
- package/dist/panels.js +155 -0
- package/dist/panels.js.map +1 -0
- package/dist/picker.d.ts +6 -0
- package/dist/picker.js +95 -0
- package/dist/picker.js.map +1 -0
- package/dist/plan.d.ts +30 -0
- package/dist/plan.js +132 -0
- package/dist/plan.js.map +1 -0
- package/dist/reduce.d.ts +45 -0
- package/dist/reduce.js +123 -0
- package/dist/reduce.js.map +1 -0
- package/dist/render.d.ts +13 -0
- package/dist/render.js +91 -0
- package/dist/render.js.map +1 -0
- package/dist/replay.d.ts +2 -0
- package/dist/replay.js +57 -0
- package/dist/replay.js.map +1 -0
- package/dist/settings.d.ts +27 -0
- package/dist/settings.js +31 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +13 -0
- package/dist/store.js +20 -0
- package/dist/store.js.map +1 -0
- package/dist/theme.d.ts +7 -0
- package/dist/theme.js +110 -0
- package/dist/theme.js.map +1 -0
- package/dist/tui.d.ts +78 -0
- package/dist/tui.js +265 -0
- package/dist/tui.js.map +1 -0
- package/package.json +58 -0
package/dist/connect.js
ADDED
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Attach to a live pi session over the relay and drive it: transcript in,
|
|
4
|
+
* prompts out. Rendering is the same reducer + pi components the replay
|
|
5
|
+
* prototype uses, so a live turn and a fixture replay draw identically.
|
|
6
|
+
*/
|
|
7
|
+
import { createInterface } from "node:readline";
|
|
8
|
+
import { createInterface as createPromptInterface } from "node:readline/promises";
|
|
9
|
+
import { SessionClient } from "./client.js";
|
|
10
|
+
import { applyTheme, availableThemes } from "./theme.js";
|
|
11
|
+
import { loadOrCreateIdentity } from "./identity.js";
|
|
12
|
+
import { parseInvite } from "./invite.js";
|
|
13
|
+
import { findCommand, } from "./commands.js";
|
|
14
|
+
import { PanelStore } from "./panels.js";
|
|
15
|
+
import { pickSession } from "./picker.js";
|
|
16
|
+
import { entriesToEnvelopes, reduce } from "./reduce.js";
|
|
17
|
+
import { Shell } from "./tui.js";
|
|
18
|
+
import { renderAgentsPanel, renderPlanPanel, summariseAgents, summarisePlan, } from "./panels.js";
|
|
19
|
+
import { renderStreaming, renderThinking, renderTranscript } from "./render.js";
|
|
20
|
+
import { loadSettings, saveSettings, settingsPath } from "./settings.js";
|
|
21
|
+
import { loadPeers, rememberPeer } from "./store.js";
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const positional = [];
|
|
24
|
+
const flags = new Map();
|
|
25
|
+
for (let i = 0; i < argv.length; i++) {
|
|
26
|
+
const arg = argv[i];
|
|
27
|
+
if (arg === "--list")
|
|
28
|
+
flags.set("list", "1");
|
|
29
|
+
else if (arg === "--list-themes")
|
|
30
|
+
flags.set("list-themes", "1");
|
|
31
|
+
else if (arg === "--debug")
|
|
32
|
+
flags.set("debug", "1");
|
|
33
|
+
else if (arg.startsWith("--"))
|
|
34
|
+
flags.set(arg.slice(2), argv[++i] ?? "");
|
|
35
|
+
else
|
|
36
|
+
positional.push(arg);
|
|
37
|
+
}
|
|
38
|
+
return { target: positional[0], flags };
|
|
39
|
+
}
|
|
40
|
+
const { target, flags } = parseArgs(process.argv.slice(2));
|
|
41
|
+
if (flags.has("list-themes")) {
|
|
42
|
+
console.log((await availableThemes()).join("\n"));
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Either a fresh `unbien://pair?…` invite, or a machine we already paired with
|
|
47
|
+
* — pairing is machine-level, so a remembered peer needs no token.
|
|
48
|
+
*/
|
|
49
|
+
function resolveTarget() {
|
|
50
|
+
const explicitRelay = flags.get("relay");
|
|
51
|
+
if (target?.startsWith("unbien://")) {
|
|
52
|
+
const relayUrl = explicitRelay ?? process.env["UNBIEN_RELAY"];
|
|
53
|
+
if (!relayUrl)
|
|
54
|
+
return null;
|
|
55
|
+
return { invite: parseInvite(target), relayUrl };
|
|
56
|
+
}
|
|
57
|
+
const peers = loadPeers();
|
|
58
|
+
const peer = target
|
|
59
|
+
? peers.find((p) => p.epk.startsWith(target) || p.name === target)
|
|
60
|
+
: peers[peers.length - 1];
|
|
61
|
+
if (!peer)
|
|
62
|
+
return null;
|
|
63
|
+
return {
|
|
64
|
+
// A remembered peer has no token; `room` is chosen after listing.
|
|
65
|
+
invite: { token: "", epk: peer.epk, roomId: "main" },
|
|
66
|
+
// A pairing is only valid on the relay it was made on, so the peer's own
|
|
67
|
+
// relay beats the ambient env var — which names whatever this shell last
|
|
68
|
+
// pointed a pi at, not where this peer lives.
|
|
69
|
+
relayUrl: explicitRelay ?? peer.relayUrl,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const resolved = resolveTarget();
|
|
73
|
+
if (!resolved) {
|
|
74
|
+
console.error("usage:\n" +
|
|
75
|
+
" unbien connect '<unbien://pair?...>' # first run: pair with a machine\n" +
|
|
76
|
+
" unbien connect [<epk-prefix>] --list # list that machine's sessions\n" +
|
|
77
|
+
" unbien connect [<epk-prefix>] --session <id> # pi session id\n" +
|
|
78
|
+
" unbien connect [<epk-prefix>] --session-name <name>\n" +
|
|
79
|
+
"options: --relay <url> (default $UNBIEN_RELAY) --name <device>\n" +
|
|
80
|
+
" --theme <name> (default: your pi theme setting) --list-themes");
|
|
81
|
+
if (loadPeers().length === 0) {
|
|
82
|
+
console.error("\nno paired machines yet — run `/unbien pair` in a session.");
|
|
83
|
+
}
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Registered BEFORE any async work: if startup stalls (relay, rooms, attach)
|
|
88
|
+
* there is no shell yet to handle keys, and raw mode left on by the picker
|
|
89
|
+
* suppresses the default Ctrl-C. Without this the process is unkillable from
|
|
90
|
+
* the terminal it is running in.
|
|
91
|
+
*/
|
|
92
|
+
// Declared BEFORE hardQuit: a SIGINT during startup runs it while the rest of
|
|
93
|
+
// this module is still initialising, and a `let` read in its temporal dead
|
|
94
|
+
// zone would throw instead of exiting.
|
|
95
|
+
let shell = null;
|
|
96
|
+
let quitting = false;
|
|
97
|
+
function hardQuit(reason) {
|
|
98
|
+
if (quitting)
|
|
99
|
+
process.exit(130);
|
|
100
|
+
quitting = true;
|
|
101
|
+
// Once the shell exists, pi owns the terminal — let its teardown run rather
|
|
102
|
+
// than restoring stdin by hand (which loses the original raw-mode state).
|
|
103
|
+
if (shell) {
|
|
104
|
+
shell.quit();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
if (process.stdin.isTTY)
|
|
109
|
+
process.stdin.setRawMode(false);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
/* stdin already torn down */
|
|
113
|
+
}
|
|
114
|
+
process.stderr.write(`\n[exit] ${reason}\n`);
|
|
115
|
+
process.exit(130);
|
|
116
|
+
}
|
|
117
|
+
process.on("SIGINT", () => hardQuit("interrupted"));
|
|
118
|
+
process.on("SIGTERM", () => hardQuit("terminated"));
|
|
119
|
+
const debug = flags.has("debug");
|
|
120
|
+
function trace(direction, detail) {
|
|
121
|
+
if (debug)
|
|
122
|
+
process.stderr.write(`[${direction}] ${detail}\n`);
|
|
123
|
+
}
|
|
124
|
+
const settings = loadSettings();
|
|
125
|
+
const appliedTheme = await applyTheme(flags.get("theme") ?? settings.theme);
|
|
126
|
+
if (appliedTheme.startsWith("dark ("))
|
|
127
|
+
console.error(`[theme] ${appliedTheme}`);
|
|
128
|
+
const { invite, relayUrl } = resolved;
|
|
129
|
+
const client = new SessionClient(relayUrl, loadOrCreateIdentity(), invite);
|
|
130
|
+
const width = process.stdout.columns ?? 100;
|
|
131
|
+
/** Frames seen so far; the transcript is re-reduced from the whole stream. */
|
|
132
|
+
const seen = [];
|
|
133
|
+
const panels = new PanelStore();
|
|
134
|
+
/** The walked session log, kept so commands can derive forks and turns. */
|
|
135
|
+
let walkedEntries = [];
|
|
136
|
+
let drawn = 0;
|
|
137
|
+
let cwd = process.cwd();
|
|
138
|
+
function emit(lines) {
|
|
139
|
+
if (shell)
|
|
140
|
+
shell.print(lines);
|
|
141
|
+
else
|
|
142
|
+
for (const line of lines)
|
|
143
|
+
console.log(line);
|
|
144
|
+
}
|
|
145
|
+
function draw() {
|
|
146
|
+
const lines = renderTranscript(reduce(seen), width, cwd, !settings.showThinking);
|
|
147
|
+
if (shell) {
|
|
148
|
+
// The shell owns the screen, so hand it the whole transcript: history
|
|
149
|
+
// replay re-reduces from scratch and would otherwise duplicate rows.
|
|
150
|
+
shell.setTranscript(lines);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
for (const line of lines.slice(drawn))
|
|
154
|
+
console.log(line);
|
|
155
|
+
}
|
|
156
|
+
drawn = lines.length;
|
|
157
|
+
}
|
|
158
|
+
/** Assistant text accumulated from deltas while a turn is in flight. */
|
|
159
|
+
let streaming = "";
|
|
160
|
+
/** Reasoning accumulated separately: it is replaced, never merged into text. */
|
|
161
|
+
let reasoning = "";
|
|
162
|
+
function paintLive() {
|
|
163
|
+
if (!shell)
|
|
164
|
+
return;
|
|
165
|
+
const parts = [];
|
|
166
|
+
if (settings.streamThinking && reasoning) {
|
|
167
|
+
parts.push(...renderThinking(reasoning, width));
|
|
168
|
+
}
|
|
169
|
+
if (streaming)
|
|
170
|
+
parts.push(...renderStreaming(streaming, width));
|
|
171
|
+
shell.setLive(parts);
|
|
172
|
+
}
|
|
173
|
+
function applyStreaming(rpc) {
|
|
174
|
+
if (!shell)
|
|
175
|
+
return;
|
|
176
|
+
const event = rpc.assistantMessageEvent;
|
|
177
|
+
switch (rpc.type) {
|
|
178
|
+
case "message_start":
|
|
179
|
+
streaming = "";
|
|
180
|
+
reasoning = "";
|
|
181
|
+
shell.setLive([]);
|
|
182
|
+
return;
|
|
183
|
+
case "message_update":
|
|
184
|
+
if (event?.type === "text_delta" && event.delta) {
|
|
185
|
+
streaming += event.delta;
|
|
186
|
+
paintLive();
|
|
187
|
+
}
|
|
188
|
+
else if (event?.type === "thinking_delta" && event.delta) {
|
|
189
|
+
reasoning += event.delta;
|
|
190
|
+
// Reasoning ends when the visible answer starts, so only paint while
|
|
191
|
+
// no text has arrived — otherwise it lingers above the real reply.
|
|
192
|
+
if (!streaming)
|
|
193
|
+
paintLive();
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
case "message_end":
|
|
197
|
+
// draw() is about to put the settled message in the transcript.
|
|
198
|
+
streaming = "";
|
|
199
|
+
reasoning = "";
|
|
200
|
+
shell.setLive([]);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Frames that can change the SETTLED transcript. Everything else (streaming
|
|
206
|
+
* deltas, partial tool output, turn lifecycle) only moves the live region or
|
|
207
|
+
* the spinner — redrawing the whole transcript for those means re-reducing and
|
|
208
|
+
* re-rendering thousands of entries hundreds of times per turn, which starves
|
|
209
|
+
* the event loop and makes the spinner stutter.
|
|
210
|
+
*/
|
|
211
|
+
const TRANSCRIPT_FRAMES = new Set([
|
|
212
|
+
"message_end",
|
|
213
|
+
"tool_execution_start",
|
|
214
|
+
"tool_execution_end",
|
|
215
|
+
"compaction_end",
|
|
216
|
+
"extension_ui_request",
|
|
217
|
+
"entry_appended",
|
|
218
|
+
]);
|
|
219
|
+
/**
|
|
220
|
+
* The pinned panel widgets, re-rendered whenever a panel arrives or a mode
|
|
221
|
+
* changes — mirroring pi-plan's widget, which lives above the composer and has
|
|
222
|
+
* hidden / collapsed / expanded states.
|
|
223
|
+
*/
|
|
224
|
+
function paintWidgets() {
|
|
225
|
+
if (!shell)
|
|
226
|
+
return;
|
|
227
|
+
const lines = [];
|
|
228
|
+
const plan = panels.get("plan");
|
|
229
|
+
const agents = panels.get("subagents");
|
|
230
|
+
if (settings.planMode === "expanded") {
|
|
231
|
+
lines.push(...renderPlanPanel(plan, {
|
|
232
|
+
showDone: settings.planShowDone,
|
|
233
|
+
showContext: settings.planShowContext,
|
|
234
|
+
maxRows: settings.planMaxRows,
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
else if (settings.planMode === "collapsed") {
|
|
238
|
+
lines.push(...summarisePlan(plan));
|
|
239
|
+
}
|
|
240
|
+
if (settings.subagentsMode === "expanded") {
|
|
241
|
+
if (lines.length > 0)
|
|
242
|
+
lines.push("");
|
|
243
|
+
lines.push(...renderAgentsPanel(agents));
|
|
244
|
+
}
|
|
245
|
+
else if (settings.subagentsMode === "collapsed") {
|
|
246
|
+
lines.push(...summariseAgents(agents));
|
|
247
|
+
}
|
|
248
|
+
shell.setWidgets(lines);
|
|
249
|
+
}
|
|
250
|
+
client.on("envelope", (env) => {
|
|
251
|
+
const kind = env.rpc ? "rpc" : env.evt ? "evt" : "ub";
|
|
252
|
+
const inner = (env.rpc ?? env.evt ?? env.ub);
|
|
253
|
+
trace("in", `${kind} ${inner?.type ?? "?"}`);
|
|
254
|
+
// Panels are ephemeral view state, not transcript.
|
|
255
|
+
if (panels.apply(env)) {
|
|
256
|
+
paintWidgets();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const rpc = env.rpc;
|
|
260
|
+
if (rpc)
|
|
261
|
+
applyStreaming(rpc);
|
|
262
|
+
seen.push(env);
|
|
263
|
+
if (!rpc || TRANSCRIPT_FRAMES.has(String(rpc.type)))
|
|
264
|
+
draw();
|
|
265
|
+
// Busy state comes from the turn lifecycle; the running tool's name makes the
|
|
266
|
+
// indicator say what it is waiting on rather than just that it is waiting.
|
|
267
|
+
if (rpc?.type === "turn_start" || rpc?.type === "agent_start") {
|
|
268
|
+
shell?.setStatus({ working: true, activity: "thinking" });
|
|
269
|
+
}
|
|
270
|
+
else if (rpc?.type === "tool_execution_start") {
|
|
271
|
+
shell?.setStatus({
|
|
272
|
+
working: true,
|
|
273
|
+
activity: String(rpc.toolName ?? "tool"),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
else if (rpc?.type === "tool_execution_end") {
|
|
277
|
+
shell?.setStatus({ working: true, activity: "thinking" });
|
|
278
|
+
}
|
|
279
|
+
else if (rpc?.type === "turn_end" ||
|
|
280
|
+
rpc?.type === "agent_end" ||
|
|
281
|
+
rpc?.type === "agent_settled") {
|
|
282
|
+
shell?.setStatus({ working: false, activity: undefined });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
client.on("relayControl", (frame) => {
|
|
286
|
+
trace("relay", String(frame.type ?? Object.keys(frame).join(",")));
|
|
287
|
+
});
|
|
288
|
+
client.on("control", (frame) => {
|
|
289
|
+
trace("in", `control ${String(frame.type)}`);
|
|
290
|
+
if (frame.type === "pair_error") {
|
|
291
|
+
console.error(`[pair failed] ${String(frame.message ?? frame.code ?? "")}`);
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
if (frame.type === "error" && frame.code === "unknown_peer") {
|
|
295
|
+
console.error("[not paired] run `/unbien pair` and pass the new invite.");
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
client.on("close", () => {
|
|
300
|
+
console.error("[relay] connection closed");
|
|
301
|
+
process.exit(1);
|
|
302
|
+
});
|
|
303
|
+
function describeSession(room, index) {
|
|
304
|
+
const label = room.name ?? room.sessionId?.slice(0, 8) ?? room.room_id;
|
|
305
|
+
const child = room.parent ? " (subagent)" : "";
|
|
306
|
+
const id = room.sessionId?.slice(0, 8) ?? room.room_id;
|
|
307
|
+
return ` ${index + 1}. ${label}${child}\n ${room.cwd ?? "?"} [${id}]`;
|
|
308
|
+
}
|
|
309
|
+
/** `--session` selects by IDENTITY: the pi sessionId (prefix ok) or room id. */
|
|
310
|
+
function matchesSessionId(room, id) {
|
|
311
|
+
return room.sessionId?.startsWith(id) === true || room.room_id === id;
|
|
312
|
+
}
|
|
313
|
+
async function pickRoom(rooms) {
|
|
314
|
+
if (rooms.length === 1)
|
|
315
|
+
return rooms[0];
|
|
316
|
+
// A non-TTY stdin (piped input, CI) can't drive a highlight list.
|
|
317
|
+
if (!process.stdin.isTTY) {
|
|
318
|
+
console.error("\nSessions on this machine:\n");
|
|
319
|
+
rooms.forEach((room, i) => console.error(describeSession(room, i)));
|
|
320
|
+
const rl = createPromptInterface({
|
|
321
|
+
input: process.stdin,
|
|
322
|
+
output: process.stderr,
|
|
323
|
+
});
|
|
324
|
+
const answer = await rl.question("\nattach to # ");
|
|
325
|
+
rl.close();
|
|
326
|
+
return rooms[Number(answer.trim()) - 1] ?? null;
|
|
327
|
+
}
|
|
328
|
+
return pickSession(rooms);
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
await client.connect();
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
console.error(`[relay] could not connect to ${relayUrl}: ${String(err)}`);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
// A token means this is a first pairing; a remembered machine skips straight
|
|
338
|
+
// to routing, since the extension auto-attaches any peer it already trusts.
|
|
339
|
+
if (invite.token) {
|
|
340
|
+
client.pair(flags.get("name") ?? "unbien-proxy");
|
|
341
|
+
rememberPeer({
|
|
342
|
+
epk: invite.epk,
|
|
343
|
+
relayUrl,
|
|
344
|
+
name: flags.get("name") ?? "unbien-proxy",
|
|
345
|
+
pairedAt: new Date().toISOString(),
|
|
346
|
+
});
|
|
347
|
+
console.error("[paired] machine remembered — future runs need no token");
|
|
348
|
+
}
|
|
349
|
+
const rooms = await client.listRooms();
|
|
350
|
+
if (rooms.length === 0) {
|
|
351
|
+
console.error("[sessions] none open — is a pi running on that machine?");
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
if (flags.has("list")) {
|
|
355
|
+
console.error("Sessions on this machine:\n");
|
|
356
|
+
rooms.forEach((room, i) => console.error(describeSession(room, i)));
|
|
357
|
+
process.exit(0);
|
|
358
|
+
}
|
|
359
|
+
const wantedId = flags.get("session");
|
|
360
|
+
const wantedName = flags.get("session-name");
|
|
361
|
+
let chosen;
|
|
362
|
+
if (wantedId) {
|
|
363
|
+
chosen = rooms.find((r) => matchesSessionId(r, wantedId)) ?? null;
|
|
364
|
+
if (!chosen)
|
|
365
|
+
console.error(`[sessions] no session with id "${wantedId}"`);
|
|
366
|
+
}
|
|
367
|
+
else if (wantedName) {
|
|
368
|
+
// Names are user-set and NOT unique, so an ambiguous one must not silently
|
|
369
|
+
// pick a session — that would attach to an arbitrary agent.
|
|
370
|
+
const named = rooms.filter((r) => r.name === wantedName);
|
|
371
|
+
if (named.length > 1) {
|
|
372
|
+
console.error(`[sessions] "${wantedName}" is ambiguous — use --session:`);
|
|
373
|
+
named.forEach((room, i) => console.error(describeSession(room, i)));
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
chosen = named[0] ?? null;
|
|
377
|
+
if (!chosen)
|
|
378
|
+
console.error(`[sessions] no session named "${wantedName}"`);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
chosen = await pickRoom(rooms);
|
|
382
|
+
}
|
|
383
|
+
if (!chosen)
|
|
384
|
+
process.exit(1);
|
|
385
|
+
client.room = chosen.room_id;
|
|
386
|
+
cwd = chosen.cwd ?? cwd;
|
|
387
|
+
console.error(`[attached] ${chosen.name ?? chosen.room_id} — ${chosen.cwd ?? "?"}\n` +
|
|
388
|
+
"type a prompt, /help for commands, Ctrl-C to exit\n");
|
|
389
|
+
// The first frame to a trusted peer is what triggers the extension's attach.
|
|
390
|
+
client.requestSync();
|
|
391
|
+
function commandContext() {
|
|
392
|
+
return {
|
|
393
|
+
client,
|
|
394
|
+
panels,
|
|
395
|
+
entries: () => walkedEntries,
|
|
396
|
+
settings,
|
|
397
|
+
saveSettings: () => {
|
|
398
|
+
saveSettings(settings);
|
|
399
|
+
paintWidgets();
|
|
400
|
+
},
|
|
401
|
+
settingsPath: settingsPath(),
|
|
402
|
+
print: emit,
|
|
403
|
+
quit: () => (shell ? shell.quit() : process.exit(0)),
|
|
404
|
+
choose: (title, items) => shell ? shell.choose(title, items) : (items[0] ?? null),
|
|
405
|
+
chooseAction: (title, items, hint, keys) => shell
|
|
406
|
+
? shell.chooseAction(title, items, hint, keys)
|
|
407
|
+
: Promise.resolve(null),
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
async function submit(text) {
|
|
411
|
+
const found = findCommand(text);
|
|
412
|
+
if (found) {
|
|
413
|
+
try {
|
|
414
|
+
await found.command.run(commandContext(), found.args);
|
|
415
|
+
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
emit([` /${found.command.name} failed: ${String(err)}`]);
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (text.startsWith("/steer "))
|
|
422
|
+
client.steer(text.slice(7));
|
|
423
|
+
else if (text.startsWith("/"))
|
|
424
|
+
emit([` unknown command: ${text}`]);
|
|
425
|
+
else {
|
|
426
|
+
trace("out", `prompt room=${client.room} chars=${text.length}`);
|
|
427
|
+
client.prompt(text);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* History is pulled AFTER the prompt box is up. `get_entries` waits on the
|
|
432
|
+
* extension, and blocking the shell on it left the terminal blank for as long
|
|
433
|
+
* as that took — with keystrokes going nowhere.
|
|
434
|
+
*/
|
|
435
|
+
async function loadHistory() {
|
|
436
|
+
const entries = await client.getEntries();
|
|
437
|
+
walkedEntries = entries;
|
|
438
|
+
if (entries.length === 0)
|
|
439
|
+
return;
|
|
440
|
+
// History is the AUTHORITATIVE prefix: it goes before anything that arrived
|
|
441
|
+
// live while we were fetching, and the transcript is rebuilt in log order.
|
|
442
|
+
seen.unshift(...entriesToEnvelopes(entries));
|
|
443
|
+
drawn = 0;
|
|
444
|
+
draw();
|
|
445
|
+
}
|
|
446
|
+
if (process.stdin.isTTY) {
|
|
447
|
+
shell = new Shell({ session: chosen.name ?? chosen.room_id, cwd: chosen.cwd ?? cwd }, (text) => void submit(text), () => {
|
|
448
|
+
// The relay socket is a live handle; leaving it open is what keeps the
|
|
449
|
+
// process alive after the TUI has gone.
|
|
450
|
+
try {
|
|
451
|
+
client.close();
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
/* already down */
|
|
455
|
+
}
|
|
456
|
+
process.exit(0);
|
|
457
|
+
});
|
|
458
|
+
shell.start();
|
|
459
|
+
// The footer's model comes from pi's own state, not from room_meta.
|
|
460
|
+
client
|
|
461
|
+
.request("get_state")
|
|
462
|
+
.then((state) => shell?.setStatus({ model: state?.model?.id }))
|
|
463
|
+
.catch(() => { });
|
|
464
|
+
void loadHistory();
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
await loadHistory();
|
|
468
|
+
const rl = createInterface({ input: process.stdin, terminal: false });
|
|
469
|
+
for await (const line of rl) {
|
|
470
|
+
const text = line.trim();
|
|
471
|
+
if (text)
|
|
472
|
+
await submit(text);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { ed25519KeypairFromSeed, generateEd25519Keypair, } from "@geohar/un-bien/client";
|
|
5
|
+
/**
|
|
6
|
+
* This client's own owner identity. It is a SEPARATE owner device from the
|
|
7
|
+
* phone — it pairs on its own token and is revoked on its own, so losing the
|
|
8
|
+
* laptop never implies re-pairing the phone.
|
|
9
|
+
*/
|
|
10
|
+
const IDENTITY_PATH = join(homedir(), ".local", "state", "un-bien", "proxy-identity.json");
|
|
11
|
+
export function loadOrCreateIdentity(path = IDENTITY_PATH) {
|
|
12
|
+
try {
|
|
13
|
+
const stored = JSON.parse(readFileSync(path, "utf8"));
|
|
14
|
+
if (stored.seed) {
|
|
15
|
+
return ed25519KeypairFromSeed(Buffer.from(stored.seed, "base64"));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// No identity yet (or an unreadable one) — mint a fresh one below.
|
|
20
|
+
}
|
|
21
|
+
const keypair = generateEd25519Keypair();
|
|
22
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
23
|
+
writeFileSync(path, JSON.stringify({
|
|
24
|
+
seed: Buffer.from(keypair.secretKey.slice(0, 32)).toString("base64"),
|
|
25
|
+
publicKey: Buffer.from(keypair.publicKey).toString("base64"),
|
|
26
|
+
}), { mode: 0o600 });
|
|
27
|
+
chmodSync(path, 0o600);
|
|
28
|
+
return keypair;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GAEvB,MAAM,wBAAwB,CAAA;AAE/B;;;;GAIG;AACH,MAAM,aAAa,GAAG,IAAI,CACxB,OAAO,EAAE,EACT,QAAQ,EACR,OAAO,EACP,SAAS,EACT,qBAAqB,CACtB,CAAA;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAI,GAAG,aAAa;IACvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAsB,CAAA;QAC1E,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,OAAO,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;QACnE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;IACrE,CAAC;IAED,MAAM,OAAO,GAAG,sBAAsB,EAAE,CAAA;IACxC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1D,aAAa,CACX,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACpE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAC7D,CAAC,EACF,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAA;IACD,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACtB,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/dist/invite.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A parsed `unbien://pair?t=…&epk=…&n=…&rm=…` invite from `/unbien pair`. */
|
|
2
|
+
export interface PairingInvite {
|
|
3
|
+
/** Single-use pairing token — opaque, echoed verbatim in `pair_request`. */
|
|
4
|
+
token: string;
|
|
5
|
+
/** Destination pi's Ed25519 public key; the outer envelope's routing `peer`. */
|
|
6
|
+
epk: string;
|
|
7
|
+
sessionName?: string;
|
|
8
|
+
roomId: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseInvite(raw: string): PairingInvite;
|
package/dist/invite.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { canonicalizeEd25519PublicKey } from "@geohar/un-bien/client";
|
|
2
|
+
export function parseInvite(raw) {
|
|
3
|
+
let url;
|
|
4
|
+
try {
|
|
5
|
+
url = new URL(raw.trim());
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
throw new Error(`not a pairing URI: ${raw}`);
|
|
9
|
+
}
|
|
10
|
+
if (url.protocol !== "unbien:" || url.host !== "pair") {
|
|
11
|
+
throw new Error(`not a pairing URI: ${raw}`);
|
|
12
|
+
}
|
|
13
|
+
const token = url.searchParams.get("t");
|
|
14
|
+
const epk = url.searchParams.get("epk");
|
|
15
|
+
if (!token)
|
|
16
|
+
throw new Error("pairing URI has no token (t)");
|
|
17
|
+
if (!epk)
|
|
18
|
+
throw new Error("pairing URI has no peer key (epk)");
|
|
19
|
+
return {
|
|
20
|
+
token,
|
|
21
|
+
// The QR carries base64url; the relay routes by standard padded base64, so
|
|
22
|
+
// canonicalize or every (peer, room) lookup misses.
|
|
23
|
+
epk: canonicalizeEd25519PublicKey(epk) ?? epk,
|
|
24
|
+
sessionName: url.searchParams.get("n") ?? undefined,
|
|
25
|
+
roomId: url.searchParams.get("rm") ?? "main",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=invite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite.js","sourceRoot":"","sources":["../src/invite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAA;AAYrE,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACvC,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;IAC3D,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAE9D,OAAO;QACL,KAAK;QACL,2EAA2E;QAC3E,oDAAoD;QACpD,GAAG,EAAE,4BAA4B,CAAC,GAAG,CAAC,IAAI,GAAG;QAC7C,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,SAAS;QACnD,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM;KAC7C,CAAA;AACH,CAAC"}
|
package/dist/main.d.ts
ADDED
package/dist/main.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Single front door: `unbien <command>`. */
|
|
3
|
+
const COMMANDS = new Map([
|
|
4
|
+
["connect", () => import("./connect.js")],
|
|
5
|
+
["replay", () => import("./replay.js")],
|
|
6
|
+
]);
|
|
7
|
+
const [command] = process.argv.slice(2);
|
|
8
|
+
const load = command ? COMMANDS.get(command) : undefined;
|
|
9
|
+
if (!load) {
|
|
10
|
+
console.error("usage: unbien <command> [options]\n\n" +
|
|
11
|
+
" connect attach to a live pi session over the relay\n" +
|
|
12
|
+
" replay render a captured envelope stream from a file\n\n" +
|
|
13
|
+
"run `unbien <command>` with no arguments for its options.");
|
|
14
|
+
process.exit(command ? 1 : 0);
|
|
15
|
+
}
|
|
16
|
+
// The subcommands parse `process.argv.slice(2)` themselves, so drop the verb.
|
|
17
|
+
process.argv.splice(2, 1);
|
|
18
|
+
await load();
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,6CAA6C;AAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;IACvB,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;CACxC,CAAC,CAAA;AAEF,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACvC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAExD,IAAI,CAAC,IAAI,EAAE,CAAC;IACV,OAAO,CAAC,KAAK,CACX,uCAAuC;QACrC,0DAA0D;QAC1D,+DAA+D;QAC/D,2DAA2D,CAC9D,CAAA;IACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC/B,CAAC;AAED,8EAA8E;AAC9E,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACzB,MAAM,IAAI,EAAE,CAAA"}
|
package/dist/panels.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EnvelopeMessage } from "./reduce.js";
|
|
2
|
+
export interface PanelItem {
|
|
3
|
+
id: string;
|
|
4
|
+
kind: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: string | null;
|
|
7
|
+
deps?: string[];
|
|
8
|
+
tainted?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface Panel {
|
|
11
|
+
key: string;
|
|
12
|
+
title: string;
|
|
13
|
+
items: PanelItem[];
|
|
14
|
+
}
|
|
15
|
+
export declare class PanelStore {
|
|
16
|
+
private readonly panels;
|
|
17
|
+
/** Returns true when the envelope was a panel update. */
|
|
18
|
+
apply(env: EnvelopeMessage): boolean;
|
|
19
|
+
get(key: string): Panel | undefined;
|
|
20
|
+
keys(): string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The plan as the app shows it: dependency waves, an `Available now` group you
|
|
24
|
+
* can pick up immediately, and a trailing `Done` — the layering pi-plan's own
|
|
25
|
+
* widget conveys by order, surfaced here as titled sections.
|
|
26
|
+
*/
|
|
27
|
+
export interface PlanViewOptions {
|
|
28
|
+
/** Include finished items. */
|
|
29
|
+
showDone?: boolean;
|
|
30
|
+
/** Include non-plan kinds (design / note context). */
|
|
31
|
+
showContext?: boolean;
|
|
32
|
+
/** Cap on rendered rows before a "…N more" trailer. */
|
|
33
|
+
maxRows?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function renderPlanPanel(panel: Panel | undefined, options?: PlanViewOptions): string[];
|
|
36
|
+
/** pi-plan's collapsed form: one line of counts, and how to expand. */
|
|
37
|
+
export declare function summarisePlan(panel: Panel | undefined): string[];
|
|
38
|
+
export declare function summariseAgents(panel: Panel | undefined): string[];
|
|
39
|
+
/** Subagents chronologically, with type badge — the app's agents panel. */
|
|
40
|
+
export declare function renderAgentsPanel(panel: Panel | undefined): string[];
|