@log0u7/opencode-mesh 0.1.2 → 0.3.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 (56) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/README.md +48 -13
  3. package/dist/index.d.ts +6 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +7 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/db.d.ts.map +1 -1
  8. package/dist/lib/db.js +19 -1
  9. package/dist/lib/db.js.map +1 -1
  10. package/dist/lib/discovery.d.ts +1 -0
  11. package/dist/lib/discovery.d.ts.map +1 -1
  12. package/dist/lib/discovery.js +27 -4
  13. package/dist/lib/discovery.js.map +1 -1
  14. package/dist/lib/identity.d.ts +0 -8
  15. package/dist/lib/identity.d.ts.map +1 -1
  16. package/dist/lib/identity.js +53 -34
  17. package/dist/lib/identity.js.map +1 -1
  18. package/dist/lib/locks.d.ts.map +1 -1
  19. package/dist/lib/locks.js +20 -12
  20. package/dist/lib/locks.js.map +1 -1
  21. package/dist/lib/peers.d.ts +9 -0
  22. package/dist/lib/peers.d.ts.map +1 -1
  23. package/dist/lib/peers.js +49 -11
  24. package/dist/lib/peers.js.map +1 -1
  25. package/dist/lib/serve.d.ts +2 -0
  26. package/dist/lib/serve.d.ts.map +1 -1
  27. package/dist/lib/serve.js +53 -68
  28. package/dist/lib/serve.js.map +1 -1
  29. package/dist/lib/spawn.d.ts +14 -4
  30. package/dist/lib/spawn.d.ts.map +1 -1
  31. package/dist/lib/spawn.js +210 -21
  32. package/dist/lib/spawn.js.map +1 -1
  33. package/dist/lib/sqlite.d.ts.map +1 -1
  34. package/dist/lib/sqlite.js +15 -4
  35. package/dist/lib/sqlite.js.map +1 -1
  36. package/dist/lib/workers.d.ts +2 -0
  37. package/dist/lib/workers.d.ts.map +1 -1
  38. package/dist/lib/workers.js +45 -12
  39. package/dist/lib/workers.js.map +1 -1
  40. package/dist/lib/worktree.d.ts +22 -4
  41. package/dist/lib/worktree.d.ts.map +1 -1
  42. package/dist/lib/worktree.js +54 -6
  43. package/dist/lib/worktree.js.map +1 -1
  44. package/dist/plugin-v2.d.ts +3 -0
  45. package/dist/plugin-v2.d.ts.map +1 -0
  46. package/dist/plugin-v2.js +108 -0
  47. package/dist/plugin-v2.js.map +1 -0
  48. package/dist/plugin.d.ts +12 -0
  49. package/dist/plugin.d.ts.map +1 -1
  50. package/dist/plugin.js +119 -266
  51. package/dist/plugin.js.map +1 -1
  52. package/dist/tools.d.ts +30 -0
  53. package/dist/tools.d.ts.map +1 -0
  54. package/dist/tools.js +308 -0
  55. package/dist/tools.js.map +1 -0
  56. package/package.json +11 -8
package/dist/tools.js ADDED
@@ -0,0 +1,308 @@
1
+ import { basename } from "node:path";
2
+ import { sendMail } from "./lib/client.js";
3
+ import { tailnetAddresses } from "./lib/discovery.js";
4
+ import { ackMessages, unreadMessages } from "./lib/mail.js";
5
+ import { listLocks, releaseLock, tryLock } from "./lib/locks.js";
6
+ import { createPairingToken, findSendablePeer, listPeers, pairWithToken, resolvePeerUrl, } from "./lib/peers.js";
7
+ import { readLogTail, removeWorkerLog, runWorker, stopWorker } from "./lib/spawn.js";
8
+ import { createWorkerWorktree, removeWorkerWorktree, } from "./lib/worktree.js";
9
+ import { deleteWorker, getWorker, listWorkers } from "./lib/workers.js";
10
+ function str(name, description, required = true) {
11
+ return { name, type: "string", required, description };
12
+ }
13
+ function num(name, description) {
14
+ return { name, type: "number", required: false, description };
15
+ }
16
+ function bool(name, description) {
17
+ return { name, type: "boolean", required: false, description };
18
+ }
19
+ export function buildToolSpecs(mesh) {
20
+ const { db, identity, dataDir, serverAddress, port, worktreeClient, spawnFn } = mesh;
21
+ return [
22
+ {
23
+ name: "mesh_status",
24
+ description: "Show this node's identity, server address, and known peers.",
25
+ fields: [],
26
+ execute: async () => {
27
+ const peers = listPeers(db);
28
+ const tailnet = await tailnetAddresses();
29
+ return JSON.stringify({
30
+ node_id: identity.node_id,
31
+ hostname: identity.hostname,
32
+ fingerprint: identity.fingerprint,
33
+ server: `${serverAddress}:${port}`,
34
+ tailnet_addresses: tailnet,
35
+ peers: peers.map((p) => ({
36
+ node_id: p.node_id,
37
+ hostname: p.hostname,
38
+ paired: p.paired,
39
+ addresses: p.addresses,
40
+ })),
41
+ locks: listLocks(db, { now: Date.now() }),
42
+ }, null, 2);
43
+ },
44
+ },
45
+ {
46
+ name: "mesh_pair",
47
+ description: "Pair with a peer. With no args: emit a pairing offer (token, node id, server address) for the peer's mesh_pair. With node_id, token, and address: complete pairing started by the other side.",
48
+ fields: [
49
+ str("node_id", "Peer node id, from its mesh_pair output", false),
50
+ str("token", "Pairing token from the peer's offer", false),
51
+ str("address", "Peer server address as host:port", false),
52
+ ],
53
+ execute: async (args) => {
54
+ const node_id = args.node_id;
55
+ const token = args.token;
56
+ const hasNodeId = typeof node_id === "string";
57
+ const hasToken = typeof token === "string";
58
+ if (hasNodeId || hasToken) {
59
+ if (!hasNodeId || !hasToken || node_id.length === 0 || token.length === 0) {
60
+ return "error: mesh_pair needs a non-empty node_id and token to complete pairing (or neither to emit an offer)";
61
+ }
62
+ pairWithToken(db, {
63
+ node_id,
64
+ hostname: "manual",
65
+ fingerprint: "manual",
66
+ token,
67
+ addresses: typeof args.address === "string" ? [args.address] : [],
68
+ });
69
+ return `paired with ${node_id}`;
70
+ }
71
+ const offer = createPairingToken(db);
72
+ return `peer should run: mesh_pair(node_id="${identity.node_id}", token="${offer}", address="${serverAddress}:${port}")`;
73
+ },
74
+ },
75
+ {
76
+ name: "mesh_send",
77
+ description: "Send a message to a paired peer's mailbox.",
78
+ fields: [
79
+ str("peer", "Peer node id or hostname"),
80
+ str("subject", "Short subject"),
81
+ str("body", "Message body"),
82
+ ],
83
+ execute: async (args) => {
84
+ const peer = String(args.peer);
85
+ const target = findSendablePeer(db, peer);
86
+ if (target === null) {
87
+ return `error: no paired peer matching ${peer}; run mesh_status`;
88
+ }
89
+ const url = resolvePeerUrl(db, peer);
90
+ if (url === null) {
91
+ return `error: peer ${target.node_id} has no known address with a port; have it run mesh_pair to share its address, or wait for discovery`;
92
+ }
93
+ const result = await sendMail({
94
+ url,
95
+ token: target.token ?? "",
96
+ from: identity.node_id,
97
+ subject: String(args.subject),
98
+ body: String(args.body),
99
+ });
100
+ return `sent to ${target.node_id}: ${result}`;
101
+ },
102
+ },
103
+ {
104
+ name: "mesh_inbox",
105
+ description: "List unread messages from peers and mark them read.",
106
+ fields: [bool("ack", "Mark messages read (default true)")],
107
+ execute: async (args) => {
108
+ const messages = unreadMessages(db);
109
+ if (messages.length === 0) {
110
+ return "inbox empty";
111
+ }
112
+ if (args.ack !== false) {
113
+ ackMessages(db, messages.map((m) => m.id));
114
+ }
115
+ return JSON.stringify(messages, null, 2);
116
+ },
117
+ },
118
+ {
119
+ name: "mesh_lock",
120
+ description: "Claim exclusive ownership of a file or path so other sessions on THIS MACHINE wait. Not distributed: a peer on another node does not see this lock.",
121
+ fields: [
122
+ str("path", "Path to lock (relative to worktree or absolute)"),
123
+ num("ttl", "Seconds before the lock expires (default 600)"),
124
+ ],
125
+ execute: async (args, context) => {
126
+ const path = String(args.path);
127
+ const granted = tryLock(db, {
128
+ path,
129
+ owner_node: identity.node_id,
130
+ owner_session: context.sessionID,
131
+ ttl_ms: (typeof args.ttl === "number" ? args.ttl : 600) * 1000,
132
+ now: Date.now(),
133
+ });
134
+ return granted
135
+ ? `locked ${path}`
136
+ : `error: ${path} is locked by another session; try later or run mesh_status`;
137
+ },
138
+ },
139
+ {
140
+ name: "mesh_unlock",
141
+ description: "Release a claim made with mesh_lock.",
142
+ fields: [str("path", "Path to unlock")],
143
+ execute: async (args) => {
144
+ const path = String(args.path);
145
+ const released = releaseLock(db, { path, owner_node: identity.node_id });
146
+ return released ? `released ${path}` : `error: ${path} was not locked by this node`;
147
+ },
148
+ },
149
+ {
150
+ name: "mesh_spawn",
151
+ description: "Run a task as a background worker in an isolated opencode worktree (headless, --auto permissions by default). Returns worker id, worktree, and branch.",
152
+ fields: [
153
+ str("task", "Task description given to the worker"),
154
+ str("name", "Worktree/branch name (random by default)", false),
155
+ str("model", "provider/model for the worker", false),
156
+ str("agent", "Agent for the worker", false),
157
+ bool("auto", "Grant all permissions to the worker (default true)"),
158
+ ],
159
+ execute: async (args) => {
160
+ let info;
161
+ try {
162
+ info = await createWorkerWorktree(worktreeClient, {
163
+ ...(typeof args.name === "string" ? { name: args.name } : {}),
164
+ });
165
+ const worker = runWorker(db, dataDir, {
166
+ task: String(args.task),
167
+ worktree_path: info.directory,
168
+ // The 2.x domain reports only the directory; fall back to its
169
+ // basename (git's branch name for the worktree) for the NOT NULL
170
+ // branch column.
171
+ branch: info.branch ?? info.name ?? basename(info.directory),
172
+ ...(typeof args.model === "string" ? { model: args.model } : {}),
173
+ ...(typeof args.agent === "string" ? { agent: args.agent } : {}),
174
+ ...(typeof args.auto === "boolean" ? { auto: args.auto } : {}),
175
+ spawnFn,
176
+ });
177
+ if (worker.status === "failed") {
178
+ // The child never ran: do not leak the worktree. Only drop the row
179
+ // once the worktree is gone, so an unclean removal stays visible.
180
+ const cleaned = await removeWorkerWorktree(worktreeClient, {
181
+ directory: info.directory,
182
+ }).catch(() => false);
183
+ info = undefined;
184
+ if (!cleaned) {
185
+ return `error: worker ${worker.id} failed to start; worktree ${worker.worktree_path} may be stranded`;
186
+ }
187
+ deleteWorker(db, worker.id);
188
+ removeWorkerLog(dataDir, worker.id);
189
+ return `error: worker ${worker.id} failed to start`;
190
+ }
191
+ return JSON.stringify({
192
+ worker_id: worker.id,
193
+ worktree: info.directory,
194
+ branch: worker.branch,
195
+ pid: worker.pid,
196
+ }, null, 2);
197
+ }
198
+ catch (error) {
199
+ const message = error instanceof Error ? error.message : String(error);
200
+ if (info) {
201
+ // A worktree was created before the failure: clean it up so a
202
+ // thrown runWorker does not strand a directory.
203
+ const cleaned = await removeWorkerWorktree(worktreeClient, {
204
+ directory: info.directory,
205
+ }).catch(() => false);
206
+ if (!cleaned) {
207
+ return `error: ${message}; worktree ${info.directory} may be stranded`;
208
+ }
209
+ }
210
+ return `error: ${message}`;
211
+ }
212
+ },
213
+ },
214
+ {
215
+ name: "mesh_workers",
216
+ description: "List spawned workers with their lifecycle state.",
217
+ fields: [],
218
+ execute: async () => {
219
+ const workers = listWorkers(db);
220
+ if (workers.length === 0) {
221
+ return "[]";
222
+ }
223
+ return JSON.stringify(workers, null, 2);
224
+ },
225
+ },
226
+ {
227
+ name: "mesh_worker_logs",
228
+ description: "Show the tail of a worker's captured output.",
229
+ fields: [
230
+ str("worker_id", "Worker id, from mesh_spawn or mesh_workers"),
231
+ num("tail", "Number of lines (default 50)"),
232
+ ],
233
+ execute: async (args) => {
234
+ const worker_id = String(args.worker_id);
235
+ const worker = getWorker(db, worker_id);
236
+ if (!worker) {
237
+ return `error: unknown worker ${worker_id}`;
238
+ }
239
+ const tail = readLogTail(dataDir, worker.id, typeof args.tail === "number" ? args.tail : 50);
240
+ return tail.length > 0 ? tail : "no log output yet";
241
+ },
242
+ },
243
+ {
244
+ name: "mesh_worker_stop",
245
+ description: "Stop a running worker (SIGTERM).",
246
+ fields: [str("worker_id", "Worker id")],
247
+ execute: async (args) => {
248
+ const worker_id = String(args.worker_id);
249
+ try {
250
+ stopWorker(db, worker_id);
251
+ return `stopped ${worker_id}`;
252
+ }
253
+ catch (error) {
254
+ return `error: ${error instanceof Error ? error.message : String(error)}`;
255
+ }
256
+ },
257
+ },
258
+ {
259
+ name: "mesh_worker_remove",
260
+ description: "Remove a finished worker: deletes the worktree (native API) and the registry row.",
261
+ fields: [
262
+ str("worker_id", "Worker id"),
263
+ bool("force", "Stop a running worker before removal"),
264
+ ],
265
+ execute: async (args) => {
266
+ const worker_id = String(args.worker_id);
267
+ const worker = getWorker(db, worker_id);
268
+ if (!worker) {
269
+ return `error: unknown worker ${worker_id}`;
270
+ }
271
+ if (worker.status === "running") {
272
+ if (args.force !== true) {
273
+ return `error: worker ${worker.id} is running; use force=true to stop and remove it`;
274
+ }
275
+ // force: terminate first so no process keeps writing into a deleted
276
+ // worktree. A row can be 'running' with no live process left (host
277
+ // restart, pid not yet reconciled): removal must still proceed.
278
+ try {
279
+ stopWorker(db, worker.id);
280
+ }
281
+ catch {
282
+ // Nothing live to signal; the registry row is what gets cleaned up.
283
+ }
284
+ }
285
+ let removed;
286
+ try {
287
+ removed = await removeWorkerWorktree(worktreeClient, {
288
+ directory: worker.worktree_path,
289
+ });
290
+ }
291
+ catch (error) {
292
+ return `error: worktree remove failed: ${error instanceof Error ? error.message : String(error)}`;
293
+ }
294
+ if (!removed) {
295
+ // Keep the row so the unremoved worktree stays discoverable.
296
+ return `error: worktree ${worker.worktree_path} was not removed; worker ${worker_id} kept`;
297
+ }
298
+ const rowDeleted = deleteWorker(db, worker_id);
299
+ if (!rowDeleted) {
300
+ return `error: worktree removed but worker row ${worker_id} was already gone`;
301
+ }
302
+ removeWorkerLog(dataDir, worker.id);
303
+ return `removed ${worker.id} (worktree, registry row and log deleted)`;
304
+ },
305
+ },
306
+ ];
307
+ }
308
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@log0u7/opencode-mesh",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Multi-session coordination for OpenCode: session coordination on one machine and a peer pool across LAN or Tailscale, with pairing, mailbox, and worktree locks.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -30,18 +30,19 @@
30
30
  "CHANGELOG.md"
31
31
  ],
32
32
  "engines": {
33
- "node": ">=22.0.0"
33
+ "node": ">=22.5.0"
34
34
  },
35
35
  "dependencies": {
36
36
  "bonjour-service": "^1.3.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@biomejs/biome": "2.5.13",
40
- "@opencode-ai/plugin": "1.18.30",
41
- "@opencode-ai/sdk": "1.18.30",
42
- "@types/node": "^22.0.0",
39
+ "@biomejs/biome": "2.5.15",
40
+ "@opencode-ai/plugin": "1.18.35",
41
+ "@opencode-ai/sdk": "1.18.35",
42
+ "@opencode/plugin": "2.0.26",
43
+ "@types/node": "^24.0.0",
43
44
  "@vitest/coverage-v8": "^5.0.1",
44
- "lefthook": "2.1.12",
45
+ "lefthook": "2.2.0",
45
46
  "typescript": "7.0.2",
46
47
  "vitest": "^5.0.0"
47
48
  },
@@ -51,9 +52,11 @@
51
52
  "check": "biome check .",
52
53
  "format": "biome format --write .",
53
54
  "typecheck": "tsc --noEmit",
55
+ "typecheck:tests": "tsc -p tsconfig.test.json",
54
56
  "test": "vitest run",
55
57
  "test:watch": "vitest",
56
58
  "test:coverage": "vitest run --coverage",
57
- "verify": "pnpm run check && pnpm run typecheck && pnpm run test"
59
+ "smoke:dist": "pnpm run build && node scripts/smoke-dist.mjs",
60
+ "verify": "pnpm run check && pnpm run typecheck && pnpm run test && pnpm run smoke:dist"
58
61
  }
59
62
  }