@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.
- package/CHANGELOG.md +136 -0
- package/README.md +48 -13
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +19 -1
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/discovery.d.ts +1 -0
- package/dist/lib/discovery.d.ts.map +1 -1
- package/dist/lib/discovery.js +27 -4
- package/dist/lib/discovery.js.map +1 -1
- package/dist/lib/identity.d.ts +0 -8
- package/dist/lib/identity.d.ts.map +1 -1
- package/dist/lib/identity.js +53 -34
- package/dist/lib/identity.js.map +1 -1
- package/dist/lib/locks.d.ts.map +1 -1
- package/dist/lib/locks.js +20 -12
- package/dist/lib/locks.js.map +1 -1
- package/dist/lib/peers.d.ts +9 -0
- package/dist/lib/peers.d.ts.map +1 -1
- package/dist/lib/peers.js +49 -11
- package/dist/lib/peers.js.map +1 -1
- package/dist/lib/serve.d.ts +2 -0
- package/dist/lib/serve.d.ts.map +1 -1
- package/dist/lib/serve.js +53 -68
- package/dist/lib/serve.js.map +1 -1
- package/dist/lib/spawn.d.ts +14 -4
- package/dist/lib/spawn.d.ts.map +1 -1
- package/dist/lib/spawn.js +210 -21
- package/dist/lib/spawn.js.map +1 -1
- package/dist/lib/sqlite.d.ts.map +1 -1
- package/dist/lib/sqlite.js +15 -4
- package/dist/lib/sqlite.js.map +1 -1
- package/dist/lib/workers.d.ts +2 -0
- package/dist/lib/workers.d.ts.map +1 -1
- package/dist/lib/workers.js +45 -12
- package/dist/lib/workers.js.map +1 -1
- package/dist/lib/worktree.d.ts +22 -4
- package/dist/lib/worktree.d.ts.map +1 -1
- package/dist/lib/worktree.js +54 -6
- package/dist/lib/worktree.js.map +1 -1
- package/dist/plugin-v2.d.ts +3 -0
- package/dist/plugin-v2.d.ts.map +1 -0
- package/dist/plugin-v2.js +108 -0
- package/dist/plugin-v2.js.map +1 -0
- package/dist/plugin.d.ts +12 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +119 -266
- package/dist/plugin.js.map +1 -1
- package/dist/tools.d.ts +30 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +308 -0
- package/dist/tools.js.map +1 -0
- package/package.json +11 -8
package/dist/lib/locks.js
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
export function tryLock(db, input) {
|
|
2
2
|
const expiresAt = input.now + input.ttl_ms;
|
|
3
3
|
db.conn.run("DELETE FROM locks WHERE expires_at <= ?", [input.now]);
|
|
4
|
+
// Claim atomically: a second opencode process sharing this dataDir that races
|
|
5
|
+
// for the same path loses the insert (ON CONFLICT DO NOTHING) instead of
|
|
6
|
+
// throwing a UNIQUE constraint error out of mesh_lock.
|
|
7
|
+
db.conn.run("INSERT INTO locks (path, owner_node, owner_session, expires_at) VALUES (?, ?, ?, ?) ON CONFLICT(path) DO NOTHING", [input.path, input.owner_node, input.owner_session, expiresAt]);
|
|
8
|
+
const claimed = (db.conn.get("SELECT changes() AS changes")?.changes ?? 0) > 0;
|
|
9
|
+
if (claimed) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
4
12
|
const existing = db.conn.get("SELECT * FROM locks WHERE path = ?", [input.path]);
|
|
5
|
-
if (existing) {
|
|
6
|
-
|
|
7
|
-
// Same owner refreshes its claim.
|
|
8
|
-
db.conn.run("UPDATE locks SET expires_at = ?, owner_session = ? WHERE path = ?", [
|
|
9
|
-
expiresAt,
|
|
10
|
-
input.owner_session,
|
|
11
|
-
input.path,
|
|
12
|
-
]);
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
13
|
+
if (!existing) {
|
|
14
|
+
// Raced with a release between the insert and this read; not granted.
|
|
15
15
|
return false;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
if (existing.owner_node === input.owner_node) {
|
|
18
|
+
// Same owner refreshes its claim.
|
|
19
|
+
db.conn.run("UPDATE locks SET expires_at = ?, owner_session = ? WHERE path = ?", [
|
|
20
|
+
expiresAt,
|
|
21
|
+
input.owner_session,
|
|
22
|
+
input.path,
|
|
23
|
+
]);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
19
27
|
}
|
|
20
28
|
export function releaseLock(db, input) {
|
|
21
29
|
db.conn.run("DELETE FROM locks WHERE path = ? AND owner_node = ?", [
|
package/dist/lib/locks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locks.js","sourceRoot":"","sources":["../../src/lib/locks.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,OAAO,CACrB,EAAU,EACV,KAA+F;IAE/F,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3C,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,yCAAyC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpE,
|
|
1
|
+
{"version":3,"file":"locks.js","sourceRoot":"","sources":["../../src/lib/locks.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,OAAO,CACrB,EAAU,EACV,KAA+F;IAE/F,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3C,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,yCAAyC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpE,8EAA8E;IAC9E,yEAAyE;IACzE,uDAAuD;IACvD,EAAE,CAAC,IAAI,CAAC,GAAG,CACT,kHAAkH,EAClH,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,aAAa,EAAE,SAAS,CAAC,CAC/D,CAAC;IACF,MAAM,OAAO,GACX,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAsB,6BAA6B,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACtF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAU,oCAAoC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1F,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,sEAAsE;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;QAC7C,kCAAkC;QAClC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,mEAAmE,EAAE;YAC/E,SAAS;YACT,KAAK,CAAC,aAAa;YACnB,KAAK,CAAC,IAAI;SACX,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,KAA2C;IACjF,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,qDAAqD,EAAE;QACjE,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,UAAU;KACjB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAsB,6BAA6B,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,KAAsB;IAC1D,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,yCAAyC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAU,mCAAmC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAClF,CAAC;AASD,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,aAAa;QACxB,OAAO,EAAE,GAAG,CAAC,UAAU;QACvB,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC"}
|
package/dist/lib/peers.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MeshDb } from "./db.js";
|
|
2
2
|
import type { Peer } from "../types/peer.js";
|
|
3
|
+
export declare const PAIRING_TOKEN_TTL_MS: number;
|
|
3
4
|
export type PeerInput = {
|
|
4
5
|
node_id: string;
|
|
5
6
|
hostname: string;
|
|
@@ -15,8 +16,16 @@ export declare function pairWithToken(db: MeshDb, peer: {
|
|
|
15
16
|
}): void;
|
|
16
17
|
export declare function createPairingToken(db: MeshDb): string;
|
|
17
18
|
export declare function authenticateToken(db: MeshDb, token: string, from: string | null): Peer | null;
|
|
19
|
+
export declare function prunePendingTokens(db: MeshDb): void;
|
|
18
20
|
export declare function listPeers(db: MeshDb): Peer[];
|
|
21
|
+
export declare function findPeerById(db: MeshDb, nodeId: string): Peer | null;
|
|
19
22
|
export declare function findPeerByToken(db: MeshDb, token: string): Peer | null;
|
|
23
|
+
export declare function findSendablePeer(db: MeshDb, query: string): {
|
|
24
|
+
node_id: string;
|
|
25
|
+
addresses: string[];
|
|
26
|
+
token: string | null;
|
|
27
|
+
} | null;
|
|
28
|
+
export declare function resolvePeerUrl(db: MeshDb, query: string): string | null;
|
|
20
29
|
export declare function upsertDiscoveredPeer(db: MeshDb, peer: {
|
|
21
30
|
node_id: string;
|
|
22
31
|
hostname: string;
|
package/dist/lib/peers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/lib/peers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../src/lib/peers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7C,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAIF,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GACA,IAAI,CAkBN;AAID,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOrD;AAKD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAkC7F;AAID,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAInD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,CAE5C;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGpE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGtE;AAGD,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAGvE;AAKD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvE;AAOD,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GACpF,IAAI,CASN"}
|
package/dist/lib/peers.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
// A pairing offer is only useful while the operator can relay it out of band.
|
|
3
|
+
// Past this age the token is dropped instead of becoming a permanent credential.
|
|
4
|
+
export const PAIRING_TOKEN_TTL_MS = 5 * 60_000;
|
|
2
5
|
// Complete pairing with a token the peer generated (shared out of band).
|
|
3
6
|
// Only the pairing call and the peer know it; the server compares on every request.
|
|
4
7
|
export function pairWithToken(db, peer) {
|
|
@@ -26,13 +29,15 @@ export function createPairingToken(db) {
|
|
|
26
29
|
]);
|
|
27
30
|
return token;
|
|
28
31
|
}
|
|
29
|
-
// Check a bearer token: known paired peer, or a pending pairing token
|
|
30
|
-
//
|
|
32
|
+
// Check a bearer token: known paired peer, or a live pending pairing token.
|
|
33
|
+
// The pending path requires the claimed sender to be a node this host already
|
|
34
|
+
// knows, so a leaked token cannot mint a permanent peer on its own.
|
|
31
35
|
export function authenticateToken(db, token, from) {
|
|
32
36
|
const paired = findPeerByToken(db, token);
|
|
33
37
|
if (paired) {
|
|
34
38
|
return paired;
|
|
35
39
|
}
|
|
40
|
+
prunePendingTokens(db);
|
|
36
41
|
const pending = db.conn.get("SELECT token FROM pending_tokens WHERE token = ?", [token]);
|
|
37
42
|
if (!pending) {
|
|
38
43
|
return null;
|
|
@@ -41,24 +46,57 @@ export function authenticateToken(db, token, from) {
|
|
|
41
46
|
if (from === null || from.length === 0) {
|
|
42
47
|
return null;
|
|
43
48
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const known = findPeerById(db, from);
|
|
50
|
+
if (!known) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
pairWithToken(db, {
|
|
54
|
+
node_id: known.node_id,
|
|
55
|
+
hostname: known.hostname,
|
|
56
|
+
fingerprint: known.fingerprint,
|
|
57
|
+
addresses: known.addresses,
|
|
51
58
|
token,
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
});
|
|
60
|
+
return known;
|
|
61
|
+
}
|
|
62
|
+
// Pairing offers are single-shot credentials with a short life: bulk delete on
|
|
63
|
+
// every check keeps the table bounded without a background timer.
|
|
64
|
+
export function prunePendingTokens(db) {
|
|
65
|
+
db.conn.run("DELETE FROM pending_tokens WHERE created_at <= ?", [
|
|
66
|
+
Date.now() - PAIRING_TOKEN_TTL_MS,
|
|
67
|
+
]);
|
|
54
68
|
}
|
|
55
69
|
export function listPeers(db) {
|
|
56
70
|
return db.conn.all("SELECT * FROM peers ORDER BY hostname").map(rowToPeer);
|
|
57
71
|
}
|
|
72
|
+
export function findPeerById(db, nodeId) {
|
|
73
|
+
const row = db.conn.get("SELECT * FROM peers WHERE node_id = ?", [nodeId]);
|
|
74
|
+
return row ? rowToPeer(row) : null;
|
|
75
|
+
}
|
|
58
76
|
export function findPeerByToken(db, token) {
|
|
59
77
|
const row = db.conn.get("SELECT * FROM peers WHERE token = ? AND paired = 1", [token]);
|
|
60
78
|
return row ? rowToPeer(row) : null;
|
|
61
79
|
}
|
|
80
|
+
// Paired peers only: discovery alone never makes a peer sendable.
|
|
81
|
+
export function findSendablePeer(db, query) {
|
|
82
|
+
const peers = listPeers(db).filter((p) => p.paired);
|
|
83
|
+
return peers.find((p) => p.node_id === query) ?? peers.find((p) => p.hostname === query) ?? null;
|
|
84
|
+
}
|
|
85
|
+
// Peer addresses must carry a port: discovery attaches the advertised port and
|
|
86
|
+
// mesh_pair transmits a full host:port. Returning null instead of guessing the
|
|
87
|
+
// local port keeps a stale address from silently reaching the wrong socket.
|
|
88
|
+
export function resolvePeerUrl(db, query) {
|
|
89
|
+
const peers = listPeers(db).filter((p) => p.paired);
|
|
90
|
+
const peer = peers.find((p) => p.node_id === query) ?? peers.find((p) => p.hostname === query) ?? null;
|
|
91
|
+
// A bare IPv6 literal also ends in ":<digits>", so the bracketed form is the
|
|
92
|
+
// only one that can be told apart unambiguously.
|
|
93
|
+
const address = peer?.addresses.find(hasPort);
|
|
94
|
+
return address !== undefined ? `http://${address}` : null;
|
|
95
|
+
}
|
|
96
|
+
function hasPort(address) {
|
|
97
|
+
// Bracketed IPv6, optionally with a zone id (e.g. `[fe80::1%eth0]:4399`).
|
|
98
|
+
return /^\[[0-9a-f:]+(?:%[^\]]+)?\]:\d+$/i.test(address) || /^[^:]+:\d+$/.test(address);
|
|
99
|
+
}
|
|
62
100
|
export function upsertDiscoveredPeer(db, peer) {
|
|
63
101
|
const now = Date.now();
|
|
64
102
|
db.conn.run(`INSERT INTO peers (node_id, hostname, fingerprint, addresses, paired, token, last_seen)
|
package/dist/lib/peers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/lib/peers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"peers.js","sourceRoot":"","sources":["../../src/lib/peers.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/serve.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ import type { MeshDb } from "./db.js";
|
|
|
3
3
|
export type MeshServerOptions = {
|
|
4
4
|
db: MeshDb;
|
|
5
5
|
port: number;
|
|
6
|
+
bind?: "loopback" | "lan";
|
|
6
7
|
};
|
|
7
8
|
export type MeshServer = {
|
|
8
9
|
server: Server;
|
|
9
10
|
port: number;
|
|
11
|
+
address: string;
|
|
10
12
|
};
|
|
11
13
|
export declare function startMeshServer(options: MeshServerOptions): Promise<MeshServer>;
|
|
12
14
|
//# sourceMappingURL=serve.d.ts.map
|
package/dist/lib/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/lib/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,MAAM,EAAkB,MAAM,WAAW,CAAC;AAGzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/lib/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,MAAM,EAAkB,MAAM,WAAW,CAAC;AAGzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAUtC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BrF"}
|
package/dist/lib/serve.js
CHANGED
|
@@ -2,30 +2,43 @@ import { createServer } from "node:http";
|
|
|
2
2
|
import { authenticateToken } from "./peers.js";
|
|
3
3
|
import { receiveMessage, unreadCount } from "./mail.js";
|
|
4
4
|
const BODY_LIMIT = 64 * 1024;
|
|
5
|
+
// Loopback by default: the mesh HTTP API must not be reachable from the
|
|
6
|
+
// network unless the operator explicitly opted into a LAN pool.
|
|
7
|
+
const DEFAULT_BIND = "127.0.0.1";
|
|
5
8
|
// Bind the mesh HTTP server and resolve the actual port. When the requested
|
|
6
9
|
// port is taken (two mesh nodes on one machine, e.g. a spawned worker loading
|
|
7
10
|
// the same plugin), fall back to an ephemeral port instead of crashing.
|
|
8
11
|
export async function startMeshServer(options) {
|
|
12
|
+
const host = options.bind === "lan" ? "0.0.0.0" : DEFAULT_BIND;
|
|
9
13
|
const server = createServer((req, res) => {
|
|
10
14
|
void handle(options.db, req, res);
|
|
11
15
|
});
|
|
16
|
+
let onListen = () => { };
|
|
12
17
|
const port = await new Promise((resolve, reject) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
server.listen(requested, () => {
|
|
22
|
-
const address = server.address();
|
|
23
|
-
resolve(address !== null && typeof address !== "string" ? address.port : requested);
|
|
24
|
-
});
|
|
18
|
+
const attempt = (requested) => {
|
|
19
|
+
onListen = () => {
|
|
20
|
+
server.removeListener("error", onError);
|
|
21
|
+
resolve(serverAddressPort(server, requested));
|
|
22
|
+
};
|
|
23
|
+
server.once("listening", onListen);
|
|
24
|
+
server.once("error", onError);
|
|
25
|
+
server.listen(requested, host);
|
|
25
26
|
};
|
|
26
|
-
|
|
27
|
+
const onError = (err) => {
|
|
28
|
+
server.removeListener("listening", onListen);
|
|
29
|
+
if (err.code === "EADDRINUSE" && server.listening === false) {
|
|
30
|
+
attempt(0);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
reject(err);
|
|
34
|
+
};
|
|
35
|
+
attempt(options.port);
|
|
27
36
|
});
|
|
28
|
-
return { server, port };
|
|
37
|
+
return { server, port, address: host };
|
|
38
|
+
}
|
|
39
|
+
function serverAddressPort(server, fallback) {
|
|
40
|
+
const address = server.address();
|
|
41
|
+
return address !== null && typeof address !== "string" ? address.port : fallback;
|
|
29
42
|
}
|
|
30
43
|
async function handle(db, req, res) {
|
|
31
44
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
@@ -38,48 +51,35 @@ async function handle(db, req, res) {
|
|
|
38
51
|
json(res, 405, { error: "method not allowed" });
|
|
39
52
|
return;
|
|
40
53
|
}
|
|
41
|
-
if (req.method === "POST") {
|
|
54
|
+
if (req.method === "POST" && url.pathname === "/mail") {
|
|
42
55
|
const body = await readBody(req);
|
|
43
|
-
if (
|
|
44
|
-
|
|
56
|
+
if ("error" in body) {
|
|
57
|
+
// A body over the limit is 413; a read failure (client aborted mid-body)
|
|
58
|
+
// is a malformed request, not an oversized one.
|
|
59
|
+
json(res, body.error === "too_large" ? 413 : 400, {
|
|
60
|
+
error: body.error === "too_large" ? "body too large" : "malformed request body",
|
|
61
|
+
});
|
|
45
62
|
return;
|
|
46
63
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
json(res, 400, { error: "invalid mail body" });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
// Authenticate with the claimed sender so pending pairing tokens bind
|
|
54
|
-
// to the node id in the message.
|
|
55
|
-
const mailPeer = authenticate(db, req, parsed.from);
|
|
56
|
-
if (!mailPeer) {
|
|
57
|
-
json(res, 401, { error: "unauthorized" });
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (parsed.from !== mailPeer.node_id) {
|
|
61
|
-
json(res, 401, { error: "from does not match token" });
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
receiveMessage(db, parsed);
|
|
65
|
-
json(res, 200, { ok: true, unread: unreadCount(db) });
|
|
64
|
+
const parsed = parseMail(body.body);
|
|
65
|
+
if (!parsed) {
|
|
66
|
+
json(res, 400, { error: "invalid mail body" });
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
// Authenticate with the claimed sender so a pending pairing token can only
|
|
70
|
+
// bind to a node this host already knows.
|
|
71
|
+
const mailPeer = authenticate(db, req, parsed.from);
|
|
72
|
+
if (!mailPeer) {
|
|
70
73
|
json(res, 401, { error: "unauthorized" });
|
|
71
74
|
return;
|
|
72
75
|
}
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
if (!parsed) {
|
|
76
|
-
json(res, 400, { error: "invalid announce body" });
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
touchAddress(db, peer.node_id, parsed.addresses);
|
|
80
|
-
json(res, 200, { ok: true });
|
|
76
|
+
if (parsed.from !== mailPeer.node_id) {
|
|
77
|
+
json(res, 401, { error: "from does not match token" });
|
|
81
78
|
return;
|
|
82
79
|
}
|
|
80
|
+
receiveMessage(db, parsed);
|
|
81
|
+
json(res, 200, { ok: true, unread: unreadCount(db) });
|
|
82
|
+
return;
|
|
83
83
|
}
|
|
84
84
|
if (req.method === "GET" && url.pathname === "/status") {
|
|
85
85
|
const peer = authenticate(db, req);
|
|
@@ -104,13 +104,6 @@ function authenticate(db, req, from = null) {
|
|
|
104
104
|
const peer = authenticateToken(db, match[1], from);
|
|
105
105
|
return peer ? { node_id: peer.node_id } : null;
|
|
106
106
|
}
|
|
107
|
-
function touchAddress(db, nodeId, addresses) {
|
|
108
|
-
db.conn.run("UPDATE peers SET addresses = ?, last_seen = ? WHERE node_id = ?", [
|
|
109
|
-
JSON.stringify(addresses),
|
|
110
|
-
Date.now(),
|
|
111
|
-
nodeId,
|
|
112
|
-
]);
|
|
113
|
-
}
|
|
114
107
|
function readBody(req) {
|
|
115
108
|
return new Promise((resolve) => {
|
|
116
109
|
const chunks = [];
|
|
@@ -127,8 +120,13 @@ function readBody(req) {
|
|
|
127
120
|
chunks.push(chunk);
|
|
128
121
|
}
|
|
129
122
|
});
|
|
130
|
-
req.on("end", () => resolve(limited ?
|
|
131
|
-
|
|
123
|
+
req.on("end", () => resolve(limited ? { error: "too_large" } : { body: Buffer.concat(chunks).toString("utf8") }));
|
|
124
|
+
// A socket error, an aborted request, or a bare close all end the read
|
|
125
|
+
// without `end`. `close` is the last-resort fallback; resolving twice is a
|
|
126
|
+
// no-op, so a normal request that already ended is unaffected.
|
|
127
|
+
req.on("error", () => resolve({ error: "read" }));
|
|
128
|
+
req.on("aborted", () => resolve({ error: "read" }));
|
|
129
|
+
req.on("close", () => resolve({ error: "read" }));
|
|
132
130
|
});
|
|
133
131
|
}
|
|
134
132
|
function parseMail(raw) {
|
|
@@ -145,19 +143,6 @@ function parseMail(raw) {
|
|
|
145
143
|
return null;
|
|
146
144
|
}
|
|
147
145
|
}
|
|
148
|
-
function parseAnnounce(raw) {
|
|
149
|
-
try {
|
|
150
|
-
const parsed = JSON.parse(raw);
|
|
151
|
-
if (!Array.isArray(parsed.addresses)) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
const addresses = parsed.addresses.filter((a) => typeof a === "string");
|
|
155
|
-
return { addresses };
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
146
|
function json(res, status, body) {
|
|
162
147
|
res.writeHead(status, { "content-type": "application/json" });
|
|
163
148
|
res.end(JSON.stringify(body));
|
package/dist/lib/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/lib/serve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/lib/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/spawn.d.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import type { MeshDb } from "./db.js";
|
|
2
2
|
import { type Worker } from "./workers.js";
|
|
3
|
+
export type DataListener = (chunk: string) => void;
|
|
3
4
|
export type SpawnedProcess = {
|
|
4
5
|
pid: number;
|
|
5
6
|
stdout: {
|
|
6
|
-
on(event: "data", listener:
|
|
7
|
+
on(event: "data", listener: DataListener): void;
|
|
8
|
+
};
|
|
9
|
+
stderr: {
|
|
10
|
+
on(event: "data", listener: DataListener): void;
|
|
7
11
|
};
|
|
8
12
|
on(event: "exit", listener: (code: number | null) => void): void;
|
|
13
|
+
on(event: "error", listener: (error: Error) => void): void;
|
|
9
14
|
kill(signal?: string): void;
|
|
10
15
|
};
|
|
11
|
-
export type SpawnFn = (argv: string[]) => SpawnedProcess;
|
|
16
|
+
export type SpawnFn = (argv: string[], env?: Record<string, string>) => SpawnedProcess;
|
|
12
17
|
export type KillFn = (id: string, signal: string) => void;
|
|
13
|
-
export declare
|
|
18
|
+
export declare const CHILD_ENV: {
|
|
19
|
+
OPENCODE_MESH_CHILD: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function nodeSpawn(argv: string[], env?: Record<string, string>): SpawnedProcess;
|
|
14
22
|
export type RunWorkerInput = {
|
|
15
23
|
task: string;
|
|
16
24
|
worktree_path: string;
|
|
@@ -19,13 +27,15 @@ export type RunWorkerInput = {
|
|
|
19
27
|
agent?: string;
|
|
20
28
|
auto?: boolean;
|
|
21
29
|
spawnFn: SpawnFn;
|
|
22
|
-
killFn?: KillFn;
|
|
23
30
|
};
|
|
24
31
|
export type StopOptions = {
|
|
25
32
|
killFn?: KillFn;
|
|
33
|
+
graceMs?: number;
|
|
26
34
|
};
|
|
27
35
|
export declare function runWorker(db: MeshDb, dataDir: string, input: RunWorkerInput): Worker;
|
|
28
36
|
export declare function stopWorker(db: MeshDb, id: string, options?: StopOptions): boolean;
|
|
29
37
|
export declare function stopAllWorkers(db: MeshDb, options?: StopOptions): void;
|
|
30
38
|
export declare function liveWorkerIds(): string[];
|
|
39
|
+
export declare function removeWorkerLog(dataDir: string, id: string): void;
|
|
40
|
+
export declare function readLogTail(dataDir: string, id: string, limit: number): string;
|
|
31
41
|
//# sourceMappingURL=spawn.d.ts.map
|
package/dist/lib/spawn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/lib/spawn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/lib/spawn.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAML,KAAK,MAAM,EAEZ,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAEnD,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE;QAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5D,MAAM,EAAE;QAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,cAAc,CAAC;AACvF,MAAM,MAAM,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAI1D,eAAO,MAAM,SAAS;IAAK,mBAAmB;CAAO,CAAC;AAItD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,cAAc,CA2CtF;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AASF,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CA8FpF;AAKD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CA4BrF;AAyBD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAQ1E;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAwDD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjE;AAQD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAoC9E"}
|