meldivo 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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/THIRD_PARTY_NOTICES.md +59 -0
  4. package/bin/meldivo.mjs +514 -0
  5. package/dist/server/harnesses/claude.js +407 -0
  6. package/dist/server/harnesses/claude.js.map +1 -0
  7. package/dist/server/harnesses/index.js +27 -0
  8. package/dist/server/harnesses/index.js.map +1 -0
  9. package/dist/server/harnesses/opencode.js +391 -0
  10. package/dist/server/harnesses/opencode.js.map +1 -0
  11. package/dist/server/harnesses/pi.js +364 -0
  12. package/dist/server/harnesses/pi.js.map +1 -0
  13. package/dist/server/harnesses/types.js +2 -0
  14. package/dist/server/harnesses/types.js.map +1 -0
  15. package/dist/server/hub.js +126 -0
  16. package/dist/server/hub.js.map +1 -0
  17. package/dist/server/index.js +515 -0
  18. package/dist/server/index.js.map +1 -0
  19. package/dist/server/logger.js +98 -0
  20. package/dist/server/logger.js.map +1 -0
  21. package/dist/server/qr.js +16 -0
  22. package/dist/server/qr.js.map +1 -0
  23. package/dist/server/remote.js +166 -0
  24. package/dist/server/remote.js.map +1 -0
  25. package/dist/server/speech.js +323 -0
  26. package/dist/server/speech.js.map +1 -0
  27. package/dist/server/state.js +91 -0
  28. package/dist/server/state.js.map +1 -0
  29. package/dist/web/apple-touch-icon.png +0 -0
  30. package/dist/web/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  31. package/dist/web/assets/browser-CujOq0-h.js +8 -0
  32. package/dist/web/assets/index-B1UGHGdh.css +1 -0
  33. package/dist/web/assets/index-CNq_igvY.js +43 -0
  34. package/dist/web/assets/index-CeWj4ejR.js +2948 -0
  35. package/dist/web/favicon-32.png +0 -0
  36. package/dist/web/index.html +15 -0
  37. package/dist/web/logo-192.png +0 -0
  38. package/dist/web/logo-512.png +0 -0
  39. package/dist/web/voice-assets/ort-wasm-simd-threaded.mjs +59 -0
  40. package/dist/web/voice-assets/ort-wasm-simd-threaded.wasm +0 -0
  41. package/dist/web/voice-assets/silero_vad_v5.onnx +0 -0
  42. package/dist/web/voice-assets/vad.worklet.bundle.min.js +1 -0
  43. package/package.json +78 -0
@@ -0,0 +1,364 @@
1
+ import { spawn } from "node:child_process";
2
+ import { readdirSync, readFileSync, readlinkSync, statSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import path from "node:path";
5
+ /** Mirrors Pi's own path-to-directory-name mangling for the sessions tree. */
6
+ function cwdToSessionDirName(cwd) {
7
+ const mangled = cwd.replace(/^[/\\]+/, "").replace(/[/\\:]/g, "-");
8
+ return `--${mangled}--`;
9
+ }
10
+ function parseJsonl(text) {
11
+ const out = [];
12
+ for (const line of text.split("\n")) {
13
+ const trimmed = line.trim();
14
+ if (!trimmed)
15
+ continue;
16
+ try {
17
+ out.push(JSON.parse(trimmed));
18
+ }
19
+ catch {
20
+ // ignore malformed lines
21
+ }
22
+ }
23
+ return out;
24
+ }
25
+ function isRealUserText(content) {
26
+ if (typeof content === "string") {
27
+ const trimmed = content.trim();
28
+ return trimmed || undefined;
29
+ }
30
+ if (Array.isArray(content)) {
31
+ for (const block of content) {
32
+ if (block && typeof block === "object" && block.type === "text") {
33
+ const text = block.text;
34
+ if (text && text.trim())
35
+ return text.trim();
36
+ }
37
+ }
38
+ }
39
+ return undefined;
40
+ }
41
+ function parseSessionFile(file) {
42
+ let stat;
43
+ try {
44
+ stat = statSync(file);
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ if (!stat.isFile())
50
+ return undefined;
51
+ let text;
52
+ try {
53
+ text = readFileSync(file, "utf8");
54
+ }
55
+ catch {
56
+ return undefined;
57
+ }
58
+ const lines = parseJsonl(text);
59
+ if (lines.length === 0)
60
+ return undefined;
61
+ const header = lines[0];
62
+ if (header?.type !== "session" || typeof header.cwd !== "string" || typeof header.id !== "string") {
63
+ return undefined;
64
+ }
65
+ let sessionInfoName;
66
+ let firstUserText;
67
+ let model;
68
+ for (const line of lines) {
69
+ if (line.type === "session_info" && typeof line.name === "string") {
70
+ sessionInfoName = line.name;
71
+ }
72
+ if (line.type === "model_change" && typeof line.provider === "string" && typeof line.modelId === "string") {
73
+ model = `${line.provider}/${line.modelId}`;
74
+ }
75
+ if (firstUserText === undefined && line.type === "message") {
76
+ const message = line.message;
77
+ if (message?.role === "user") {
78
+ const text = isRealUserText(message.content);
79
+ if (text)
80
+ firstUserText = text;
81
+ }
82
+ }
83
+ }
84
+ return {
85
+ id: header.id,
86
+ cwd: header.cwd,
87
+ title: sessionInfoName ?? firstUserText ?? "(untitled)",
88
+ model,
89
+ updatedAt: stat.mtimeMs,
90
+ };
91
+ }
92
+ function readCmdline(pid) {
93
+ try {
94
+ const raw = readFileSync(`/proc/${pid}/cmdline`, "utf8");
95
+ return raw.split("\0").filter((v) => v.length > 0);
96
+ }
97
+ catch {
98
+ return [];
99
+ }
100
+ }
101
+ function readCwd(pid) {
102
+ try {
103
+ return readlinkSync(`/proc/${pid}/cwd`);
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ /** Finds running `pi` interactive/attached processes (not headless one-shot turns we spawned). */
110
+ function findOpenPiProcesses() {
111
+ const results = [];
112
+ let pids;
113
+ try {
114
+ pids = readdirSync("/proc").filter((p) => /^\d+$/.test(p));
115
+ }
116
+ catch {
117
+ return results;
118
+ }
119
+ for (const pid of pids) {
120
+ const args = readCmdline(pid);
121
+ if (args.length === 0)
122
+ continue;
123
+ const isNode = /node$/.test(args[0] ?? "");
124
+ const scriptArg = isNode ? args[1] : args[0];
125
+ if (!scriptArg || !/\/(pi|pi-coding-agent)$/.test(scriptArg))
126
+ continue;
127
+ if (args.includes("--mode")) {
128
+ const modeIdx = args.indexOf("--mode");
129
+ const mode = args[modeIdx + 1];
130
+ if (mode === "json" || mode === "rpc")
131
+ continue;
132
+ }
133
+ if (args.includes("-p") || args.includes("--print"))
134
+ continue;
135
+ const cwd = readCwd(pid);
136
+ if (!cwd)
137
+ continue;
138
+ let sessionArg;
139
+ const sessionIdx = args.indexOf("--session");
140
+ if (sessionIdx >= 0 && args[sessionIdx + 1])
141
+ sessionArg = args[sessionIdx + 1];
142
+ results.push({ cwd, sessionArg });
143
+ }
144
+ return results;
145
+ }
146
+ export function createPiAdapter(options = {}) {
147
+ const home = options.home ?? homedir();
148
+ const bin = options.bin ?? "pi";
149
+ const sessionsDir = path.join(home, ".pi", "agent", "sessions");
150
+ let availableCache;
151
+ async function checkAvailable() {
152
+ return new Promise((resolve) => {
153
+ const child = spawn(bin, ["--version"], { stdio: "ignore" });
154
+ child.on("error", () => resolve(false));
155
+ child.on("exit", (code) => resolve(code === 0));
156
+ });
157
+ }
158
+ function listSessionFiles() {
159
+ let dirs;
160
+ try {
161
+ dirs = readdirSync(sessionsDir);
162
+ }
163
+ catch {
164
+ return [];
165
+ }
166
+ const files = [];
167
+ for (const dir of dirs) {
168
+ const full = path.join(sessionsDir, dir);
169
+ let stat;
170
+ try {
171
+ stat = statSync(full);
172
+ }
173
+ catch {
174
+ continue;
175
+ }
176
+ if (!stat.isDirectory())
177
+ continue;
178
+ let entries;
179
+ try {
180
+ entries = readdirSync(full);
181
+ }
182
+ catch {
183
+ continue;
184
+ }
185
+ for (const entry of entries) {
186
+ if (entry.endsWith(".jsonl"))
187
+ files.push(path.join(full, entry));
188
+ }
189
+ }
190
+ return files;
191
+ }
192
+ return {
193
+ id: "pi",
194
+ label: "Pi",
195
+ async available() {
196
+ const now = Date.now();
197
+ if (availableCache && now - availableCache.at < 60_000)
198
+ return availableCache.value;
199
+ const value = await checkAvailable();
200
+ availableCache = { value, at: now };
201
+ return value;
202
+ },
203
+ async listSessions(limit) {
204
+ const files = listSessionFiles();
205
+ const parsed = files
206
+ .map((file) => parseSessionFile(file))
207
+ .filter((v) => v !== undefined)
208
+ .sort((a, b) => b.updatedAt - a.updatedAt);
209
+ const openProcs = findOpenPiProcesses();
210
+ const openSessionIds = new Set();
211
+ const cwdsWithoutExplicitSession = new Set();
212
+ for (const proc of openProcs) {
213
+ const sessionArg = proc.sessionArg;
214
+ if (sessionArg) {
215
+ const match = parsed.find((s) => s.id === sessionArg || s.id.startsWith(sessionArg));
216
+ if (match)
217
+ openSessionIds.add(match.id);
218
+ }
219
+ else {
220
+ cwdsWithoutExplicitSession.add(proc.cwd);
221
+ }
222
+ }
223
+ for (const cwd of cwdsWithoutExplicitSession) {
224
+ const match = parsed.find((s) => s.cwd === cwd);
225
+ if (match)
226
+ openSessionIds.add(match.id);
227
+ }
228
+ const capped = limit ? parsed.slice(0, limit) : parsed;
229
+ return capped.map((s) => {
230
+ const open = openSessionIds.has(s.id);
231
+ return {
232
+ key: `pi:${s.id}`,
233
+ harness: "pi",
234
+ id: s.id,
235
+ title: s.title,
236
+ cwd: s.cwd,
237
+ updatedAt: s.updatedAt,
238
+ open,
239
+ model: s.model,
240
+ };
241
+ });
242
+ },
243
+ async *send(target, text, signal) {
244
+ const args = ["--mode", "json"];
245
+ let sessionFile;
246
+ if (target.id) {
247
+ sessionFile = resolveSessionFile(sessionsDir, target.cwd, target.id);
248
+ if (target.fork) {
249
+ args.push("--fork", sessionFile ?? target.id);
250
+ }
251
+ else {
252
+ args.push("--session", sessionFile ?? target.id);
253
+ }
254
+ }
255
+ if (target.model)
256
+ args.push("--model", target.model);
257
+ args.push(text);
258
+ const child = spawn(bin, args, {
259
+ cwd: target.cwd,
260
+ stdio: ["ignore", "pipe", "pipe"],
261
+ });
262
+ const onAbort = () => child.kill("SIGTERM");
263
+ signal.addEventListener("abort", onAbort, { once: true });
264
+ let stderrTail = "";
265
+ child.stderr.on("data", (chunk) => {
266
+ stderrTail = (stderrTail + chunk.toString("utf8")).slice(-4000);
267
+ });
268
+ let buffered = "";
269
+ const events = [];
270
+ let resolveNext;
271
+ let ended = false;
272
+ let exitCode = null;
273
+ child.stdout.on("data", (chunk) => {
274
+ buffered += chunk.toString("utf8");
275
+ let idx;
276
+ while ((idx = buffered.indexOf("\n")) >= 0) {
277
+ const raw = buffered.slice(0, idx).replace(/\r$/, "");
278
+ buffered = buffered.slice(idx + 1);
279
+ if (!raw.trim())
280
+ continue;
281
+ let obj;
282
+ try {
283
+ obj = JSON.parse(raw);
284
+ }
285
+ catch {
286
+ continue;
287
+ }
288
+ handleEvent(obj);
289
+ }
290
+ });
291
+ function handleEvent(obj) {
292
+ const type = obj.type;
293
+ if (type === "session" && typeof obj.id === "string") {
294
+ events.push({ type: "session", id: obj.id });
295
+ }
296
+ else if (type === "message_update") {
297
+ const ev = obj.assistantMessageEvent;
298
+ if (ev?.type === "text_delta" && typeof ev.delta === "string") {
299
+ events.push({ type: "delta", text: ev.delta });
300
+ }
301
+ }
302
+ else if (type === "tool_execution_start") {
303
+ const name = obj.toolName;
304
+ if (typeof name === "string")
305
+ events.push({ type: "tool", name });
306
+ }
307
+ resolveNext?.();
308
+ }
309
+ const exitPromise = new Promise((resolve) => {
310
+ child.on("close", (code) => {
311
+ exitCode = code;
312
+ ended = true;
313
+ resolveNext?.();
314
+ resolve();
315
+ });
316
+ child.on("error", (err) => {
317
+ stderrTail += `\n${String(err)}`;
318
+ exitCode = -1;
319
+ ended = true;
320
+ resolveNext?.();
321
+ resolve();
322
+ });
323
+ });
324
+ try {
325
+ while (true) {
326
+ while (events.length > 0) {
327
+ yield events.shift();
328
+ }
329
+ if (ended)
330
+ break;
331
+ await new Promise((resolve) => {
332
+ resolveNext = resolve;
333
+ });
334
+ }
335
+ await exitPromise;
336
+ while (events.length > 0) {
337
+ yield events.shift();
338
+ }
339
+ if (exitCode !== 0 && exitCode !== null) {
340
+ yield { type: "error", message: stderrTail.trim() || `pi exited with code ${exitCode}` };
341
+ }
342
+ }
343
+ finally {
344
+ signal.removeEventListener("abort", onAbort);
345
+ yield { type: "done" };
346
+ }
347
+ },
348
+ };
349
+ }
350
+ /** Finds the on-disk session file for `id` under `sessionsDir` for the given cwd's session folder. */
351
+ function resolveSessionFile(sessionsDir, cwd, id) {
352
+ const dirName = cwdToSessionDirName(cwd);
353
+ const dir = path.join(sessionsDir, dirName);
354
+ let entries;
355
+ try {
356
+ entries = readdirSync(dir);
357
+ }
358
+ catch {
359
+ return undefined;
360
+ }
361
+ const match = entries.find((e) => e.endsWith(".jsonl") && e.includes(id));
362
+ return match ? path.join(dir, match) : undefined;
363
+ }
364
+ //# sourceMappingURL=pi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.js","sourceRoot":"","sources":["../../../server/src/harnesses/pi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../server/src/harnesses/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,126 @@
1
+ import { randomBytes, randomUUID } from "node:crypto";
2
+ // A room is a single Pi session's voice capability: one bearer token grants
3
+ // access to its chat turns and adapter queue. Rooms are pruned after
4
+ // `roomTtlMs` of inactivity so a crashed or forgotten Pi session does not
5
+ // linger forever.
6
+ export class MeldivoHub {
7
+ roomTtlMs;
8
+ rooms = new Map();
9
+ constructor(roomTtlMs) {
10
+ this.roomTtlMs = roomTtlMs;
11
+ }
12
+ create(input) {
13
+ this.prune();
14
+ const now = Date.now();
15
+ const room = {
16
+ id: randomUUID(),
17
+ token: randomBytes(32).toString("base64url"),
18
+ mode: "harness",
19
+ harness: input.harness,
20
+ cwd: input.cwd,
21
+ label: input.label,
22
+ state: "ready",
23
+ createdAt: now,
24
+ updatedAt: now,
25
+ queuedTurns: [],
26
+ };
27
+ this.rooms.set(room.id, room);
28
+ return { room: publicRoom(room), token: room.token };
29
+ }
30
+ authorize(roomId, token) {
31
+ this.prune();
32
+ if (!roomId || !token)
33
+ return undefined;
34
+ const room = this.rooms.get(roomId);
35
+ if (!room || room.state !== "ready" || !timingSafeEqual(room.token, token))
36
+ return undefined;
37
+ room.updatedAt = Date.now();
38
+ return room;
39
+ }
40
+ // A trusted (bootstrap-secret-authenticated) caller may look up a room by id
41
+ // alone, without presenting its capability token.
42
+ get(roomId) {
43
+ this.prune();
44
+ const room = this.rooms.get(roomId);
45
+ return room && room.state === "ready" ? room : undefined;
46
+ }
47
+ // Voice endpoints are not scoped to one room in their URL, so this checks
48
+ // whether a token belongs to any currently open room.
49
+ authorizeToken(token) {
50
+ this.prune();
51
+ if (!token)
52
+ return undefined;
53
+ for (const room of this.rooms.values()) {
54
+ if (room.state === "ready" && timingSafeEqual(room.token, token))
55
+ return room;
56
+ }
57
+ return undefined;
58
+ }
59
+ public(room) {
60
+ return publicRoom(room);
61
+ }
62
+ size() {
63
+ this.prune();
64
+ return this.rooms.size;
65
+ }
66
+ close(room) {
67
+ room.state = "closed";
68
+ room.queuedTurns = [];
69
+ room.updatedAt = Date.now();
70
+ this.rooms.delete(room.id);
71
+ }
72
+ enqueueTurn(room, message) {
73
+ const turn = { turnId: randomUUID(), message, cwd: room.cwd, harness: room.harness, delivered: false };
74
+ room.queuedTurns.push(turn);
75
+ room.updatedAt = Date.now();
76
+ return turn;
77
+ }
78
+ nextTurn(room) {
79
+ const turn = room.queuedTurns.find((item) => !item.delivered);
80
+ if (!turn)
81
+ return undefined;
82
+ turn.delivered = true;
83
+ room.updatedAt = Date.now();
84
+ return { turnId: turn.turnId, message: turn.message, cwd: turn.cwd, harness: turn.harness };
85
+ }
86
+ removeTurn(room, turnId) {
87
+ room.queuedTurns = room.queuedTurns.filter((turn) => turn.turnId !== turnId);
88
+ room.updatedAt = Date.now();
89
+ }
90
+ removeTurnById(roomId, turnId) {
91
+ const room = this.rooms.get(roomId);
92
+ if (room)
93
+ this.removeTurn(room, turnId);
94
+ }
95
+ prune() {
96
+ if (this.roomTtlMs <= 0)
97
+ return;
98
+ const threshold = Date.now() - this.roomTtlMs;
99
+ for (const [id, room] of this.rooms) {
100
+ if (room.updatedAt < threshold)
101
+ this.rooms.delete(id);
102
+ }
103
+ }
104
+ }
105
+ function publicRoom(room) {
106
+ return {
107
+ id: room.id,
108
+ mode: room.mode,
109
+ harness: room.harness,
110
+ ...(room.cwd ? { cwd: room.cwd } : {}),
111
+ ...(room.label ? { label: room.label } : {}),
112
+ state: room.state,
113
+ createdAt: new Date(room.createdAt).toISOString(),
114
+ };
115
+ }
116
+ function timingSafeEqual(a, b) {
117
+ // Tokens are fixed-size values when created by this hub. Avoid an early-return
118
+ // comparison so a room URL cannot be guessed by timing requests.
119
+ if (a.length !== b.length)
120
+ return false;
121
+ let result = 0;
122
+ for (let index = 0; index < a.length; index++)
123
+ result |= a.charCodeAt(index) ^ b.charCodeAt(index);
124
+ return result === 0;
125
+ }
126
+ //# sourceMappingURL=hub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hub.js","sourceRoot":"","sources":["../../server/src/hub.ts"],"names":[],"mappings":"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"}