rovloom 0.5.0 → 0.6.1
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 +9 -1
- package/dist/src/admin/index.js +1 -1
- package/dist/src/{chunk-emcefrc1.js → chunk-0e9gg4sg.js} +3 -4
- package/dist/src/chunk-1xer1ent.js +102 -0
- package/dist/src/{chunk-863tk45b.js → chunk-41fny9qm.js} +5 -5
- package/dist/src/{chunk-zjzrcc59.js → chunk-59h200cr.js} +139 -7
- package/dist/src/chunk-5w5srj3b.js +93 -0
- package/dist/src/{chunk-d4ejrtjq.js → chunk-6n6b1xpy.js} +1 -1
- package/dist/src/{chunk-ympzv86c.js → chunk-6w4g9fw8.js} +16 -4
- package/dist/src/{chunk-smpevv7n.js → chunk-73aq2qkz.js} +9 -16
- package/dist/src/{chunk-0ake7e4r.js → chunk-8c9yc0ge.js} +9 -17
- package/dist/src/{chunk-57ayxqnb.js → chunk-8fy8w7ds.js} +2 -23
- package/dist/src/{chunk-64ftwe9b.js → chunk-8ykrqhxh.js} +8 -2
- package/dist/src/{chunk-2tn0r64b.js → chunk-9h9x79bx.js} +5 -5
- package/dist/src/{chunk-nyn75b8v.js → chunk-av31bx1e.js} +31 -2
- package/dist/src/{chunk-0xgpxdgc.js → chunk-bbdtsg4b.js} +7 -5
- package/dist/src/{chunk-q5pgbwb3.js → chunk-e7jgpxkf.js} +2 -2
- package/dist/src/{chunk-zj48jvfe.js → chunk-efty77sb.js} +3 -40
- package/dist/src/{chunk-abd4envz.js → chunk-enj7s8cv.js} +71 -78
- package/dist/src/{chunk-4etdq0cp.js → chunk-ftpy8xx3.js} +313 -28
- package/dist/src/{chunk-zdxww7ms.js → chunk-h3xyq7zk.js} +1 -1
- package/dist/src/{chunk-ttsrctxg.js → chunk-hxmq28pg.js} +9 -7
- package/dist/src/{chunk-r0nfthsf.js → chunk-j59ac0xs.js} +2 -2
- package/dist/src/{chunk-5s2emvww.js → chunk-j6svdqr8.js} +10 -302
- package/dist/src/{chunk-9y36gntb.js → chunk-jkzfck98.js} +10 -5
- package/dist/src/{chunk-sj24fpz3.js → chunk-m76cmkfy.js} +28 -30
- package/dist/src/{chunk-5n8csngz.js → chunk-m96mbzcw.js} +816 -305
- package/dist/src/{chunk-xhq21g24.js → chunk-m9c1pnv9.js} +3 -3
- package/dist/src/{chunk-fnakrk0a.js → chunk-n3z3jaxy.js} +39 -36
- package/dist/src/{chunk-e7x51y0t.js → chunk-ndj0ay2p.js} +19 -18
- package/dist/src/chunk-pgs9jp6t.js +320 -0
- package/dist/src/chunk-pksaqt9a.js +25 -0
- package/dist/src/{chunk-ebm3kvnq.js → chunk-pnep7yhj.js} +31 -100
- package/dist/src/chunk-qn5xae7g.js +66 -0
- package/dist/src/{chunk-0pewfj89.js → chunk-qp8tgms2.js} +1 -1
- package/dist/src/{chunk-7k9g0x5e.js → chunk-rmgw8h27.js} +10 -8
- package/dist/src/{chunk-gbsbwssz.js → chunk-sf4ztxba.js} +3 -3
- package/dist/src/{chunk-7q96e161.js → chunk-shez7hkc.js} +6 -12
- package/dist/src/chunk-sqz614bh.js +30 -0
- package/dist/src/{chunk-09f9q26d.js → chunk-vdwzb63d.js} +2 -2
- package/dist/src/chunk-xtvgm6kf.js +48 -0
- package/dist/src/chunk-y8zm75jt.js +157 -0
- package/dist/src/chunk-yasqw2vj.js +756 -0
- package/dist/src/{chunk-ybte82d3.js → chunk-z0qmfqvd.js} +4 -3
- package/dist/src/chunk-zm705snh.js +53 -0
- package/dist/src/cli/index.js +39 -30
- package/dist/src/cli/main.js +14 -9
- package/dist/src/connector/herdr/installation.js +4 -4
- package/dist/src/connector/herdr/provider.js +9 -9
- package/dist/src/connector/herdr/runtime.js +7 -7
- package/dist/src/connector/luvus/index.js +7 -6
- package/dist/src/mcp/index.js +16 -14
- package/dist/src/runtime/index.js +16 -15
- package/dist/src/service/index.js +3 -4
- package/dist/src/store.js +4 -4
- package/dist/src/transport/index.js +9 -9
- package/dist/src/webui/index.js +975 -834
- package/package.json +1 -1
- package/dist/src/chunk-5j0gj6w2.js +0 -7
- package/dist/src/chunk-9yg6x3gt.js +0 -24
- package/dist/src/chunk-erdq0rn8.js +0 -1300
- package/dist/src/chunk-n073xnr1.js +0 -1117
- package/dist/src/chunk-rwpynx2j.js +0 -51
- package/dist/src/chunk-vwcntax3.js +0 -228
package/README.md
CHANGED
|
@@ -45,9 +45,17 @@ always-on host runs the Gateway. Your AI client reaches the Gateway over MCP and
|
|
|
45
45
|
workstation's real sessions.
|
|
46
46
|
|
|
47
47
|
1. On the Gateway host: `rovloom gateway`.
|
|
48
|
-
2. On the workstation:
|
|
48
|
+
2. On the workstation: paste the join command the Gateway prints (`rovloom connector --join ws://…#code`).
|
|
49
49
|
3. Add the Gateway's MCP URL and Bearer to your AI client and ask it to list the workstation's workspaces.
|
|
50
50
|
|
|
51
|
+
## CLI language
|
|
52
|
+
|
|
53
|
+
CLI output (help, join messages, status hints) is English by default. Set `ROVLOOM_LANG=zh-CN`
|
|
54
|
+
to switch to Simplified Chinese; without it the CLI stays in English regardless of the system
|
|
55
|
+
locale (`LC_ALL`/`LANG` have no effect). Error and status codes (`config_valid`,
|
|
56
|
+
`pairing_required`, …) are stable identifiers and never change with the language. The management
|
|
57
|
+
page picks its language in the browser, independently of this setting.
|
|
58
|
+
|
|
51
59
|
## Install
|
|
52
60
|
|
|
53
61
|
```sh
|
package/dist/src/admin/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
SERVICE_HELP2,
|
|
4
3
|
parseServiceCommand2,
|
|
5
4
|
handleServiceCommand2
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-shez7hkc.js";
|
|
6
|
+
import"./chunk-pgs9jp6t.js";
|
|
7
7
|
export {
|
|
8
|
-
SERVICE_HELP2 as SERVICE_HELP,
|
|
9
8
|
handleServiceCommand2 as handleServiceCommand,
|
|
10
9
|
parseServiceCommand2 as parseServiceCommand
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
//# debugId=
|
|
12
|
+
//# debugId=2172CFBA81B35CDA64756E2164756E21
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
boundedJson2
|
|
4
|
+
} from "./chunk-qt9m2kg2.js";
|
|
5
|
+
import {
|
|
6
|
+
readRuntimeJson
|
|
7
|
+
} from "./chunk-z7kkfrgz.js";
|
|
8
|
+
import {
|
|
9
|
+
CliError2
|
|
10
|
+
} from "./chunk-hpzr94hm.js";
|
|
11
|
+
import {
|
|
12
|
+
privatePath,
|
|
13
|
+
readPrivateBytes
|
|
14
|
+
} from "./chunk-0y5542k8.js";
|
|
15
|
+
|
|
16
|
+
// src/cli/setup-files.ts
|
|
17
|
+
import {
|
|
18
|
+
closeSync,
|
|
19
|
+
fsyncSync,
|
|
20
|
+
fchmodSync,
|
|
21
|
+
linkSync,
|
|
22
|
+
statSync,
|
|
23
|
+
openSync,
|
|
24
|
+
renameSync,
|
|
25
|
+
unlinkSync,
|
|
26
|
+
writeFileSync
|
|
27
|
+
} from "fs";
|
|
28
|
+
import { createHash, randomUUID } from "crypto";
|
|
29
|
+
import { dirname, join } from "path";
|
|
30
|
+
function setupFileStamp(path) {
|
|
31
|
+
const bytes = readPrivateBytes(path, 16777216);
|
|
32
|
+
try {
|
|
33
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
34
|
+
} finally {
|
|
35
|
+
bytes.fill(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function writeSetupFile(path, bytes, replace = false, expectedStamp) {
|
|
39
|
+
privatePath(path);
|
|
40
|
+
const previous = replace ? expectedStamp ?? setupFileStamp(path) : undefined;
|
|
41
|
+
if (replace && setupFileStamp(path) !== previous) {
|
|
42
|
+
throw new CliError2("config_changed");
|
|
43
|
+
}
|
|
44
|
+
const temporary = join(dirname(path), ".rovloom-setup-" + randomUUID() + ".tmp");
|
|
45
|
+
let fd;
|
|
46
|
+
let created = false;
|
|
47
|
+
try {
|
|
48
|
+
const mode = replace ? statSync(path).mode & 511 : 384;
|
|
49
|
+
fd = openSync(temporary, "wx", mode);
|
|
50
|
+
created = true;
|
|
51
|
+
if (replace && process.platform !== "win32") {
|
|
52
|
+
fchmodSync(fd, mode);
|
|
53
|
+
}
|
|
54
|
+
writeFileSync(fd, bytes);
|
|
55
|
+
fsyncSync(fd);
|
|
56
|
+
const complete = fd;
|
|
57
|
+
fd = undefined;
|
|
58
|
+
closeSync(complete);
|
|
59
|
+
if (replace) {
|
|
60
|
+
if (setupFileStamp(path) !== previous) {
|
|
61
|
+
throw new CliError2("config_changed");
|
|
62
|
+
}
|
|
63
|
+
renameSync(temporary, path);
|
|
64
|
+
} else {
|
|
65
|
+
linkSync(temporary, path);
|
|
66
|
+
unlinkSync(temporary);
|
|
67
|
+
}
|
|
68
|
+
created = false;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error instanceof CliError2) {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
throw new CliError2("config_unreadable");
|
|
74
|
+
} finally {
|
|
75
|
+
try {
|
|
76
|
+
if (fd !== undefined) {
|
|
77
|
+
closeSync(fd);
|
|
78
|
+
}
|
|
79
|
+
} finally {
|
|
80
|
+
if (created) {
|
|
81
|
+
unlinkSync(temporary);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function readSetupJson(path, maximum = 16384) {
|
|
87
|
+
try {
|
|
88
|
+
return readRuntimeJson(path, maximum);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof CliError2 && error.code === "backend_unavailable") {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function writeSetupJson(path, value, replace = false, maximum = 16384) {
|
|
97
|
+
writeSetupFile(path, boundedJson2(value, maximum), replace);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { setupFileStamp, writeSetupFile, readSetupJson, writeSetupJson };
|
|
101
|
+
|
|
102
|
+
//# debugId=F153F55644C9BB1764756E2164756E21
|
|
@@ -10,9 +10,6 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
compileHerdrSchemas2
|
|
12
12
|
} from "./chunk-5h82060k.js";
|
|
13
|
-
import {
|
|
14
|
-
ConnectorCapacityError
|
|
15
|
-
} from "./chunk-57ayxqnb.js";
|
|
16
13
|
import {
|
|
17
14
|
HerdrLocalError,
|
|
18
15
|
readHerdrPeer,
|
|
@@ -23,7 +20,10 @@ import {
|
|
|
23
20
|
measureHerdrInstallation,
|
|
24
21
|
verifyHerdrInstallation,
|
|
25
22
|
isHerdrInstanceBinding
|
|
26
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-e7jgpxkf.js";
|
|
24
|
+
import {
|
|
25
|
+
ConnectorCapacityError
|
|
26
|
+
} from "./chunk-pksaqt9a.js";
|
|
27
27
|
|
|
28
28
|
// src/connector/herdr/io.ts
|
|
29
29
|
import { spawn } from "child_process";
|
|
@@ -430,4 +430,4 @@ function createHerdrHostServices2(installation, services) {
|
|
|
430
430
|
|
|
431
431
|
export { isStoppedHerdrCommandCancellation, checkHerdrSignal, herdrDeadline, runHerdrCommand, withHerdrSocket, exchangeHerdr, HerdrInstallation2, createHerdrHostServices2 };
|
|
432
432
|
|
|
433
|
-
//# debugId=
|
|
433
|
+
//# debugId=C2DD57901BB8C75064756E2164756E21
|
|
@@ -25,16 +25,16 @@ import {
|
|
|
25
25
|
decodeWireFrame2,
|
|
26
26
|
discardFencedWireFrame2
|
|
27
27
|
} from "./chunk-qt9m2kg2.js";
|
|
28
|
-
import {
|
|
29
|
-
LuvusAdapterError2,
|
|
30
|
-
ConnectorCapacityError
|
|
31
|
-
} from "./chunk-57ayxqnb.js";
|
|
32
28
|
import {
|
|
33
29
|
HerdrLocalError
|
|
34
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-e7jgpxkf.js";
|
|
35
31
|
import {
|
|
36
32
|
createLuvusWireAdapter2
|
|
37
33
|
} from "./chunk-hz8pm6hz.js";
|
|
34
|
+
import {
|
|
35
|
+
LuvusAdapterError2,
|
|
36
|
+
ConnectorCapacityError
|
|
37
|
+
} from "./chunk-pksaqt9a.js";
|
|
38
38
|
|
|
39
39
|
// src/transport/gateway.ts
|
|
40
40
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -1795,6 +1795,138 @@ function createConnector2(options) {
|
|
|
1795
1795
|
}
|
|
1796
1796
|
};
|
|
1797
1797
|
}
|
|
1798
|
+
// src/transport/pairing.ts
|
|
1799
|
+
class PairingAdmin2 {
|
|
1800
|
+
store;
|
|
1801
|
+
host;
|
|
1802
|
+
constructor(store, host) {
|
|
1803
|
+
this.store = store;
|
|
1804
|
+
this.host = host;
|
|
1805
|
+
}
|
|
1806
|
+
register(name) {
|
|
1807
|
+
if (this.host.authorize("register") !== undefined) {
|
|
1808
|
+
fail2("pairing_admin_forbidden");
|
|
1809
|
+
}
|
|
1810
|
+
return this.store.register(name);
|
|
1811
|
+
}
|
|
1812
|
+
issue(machine, ttlMs = 600000) {
|
|
1813
|
+
if (this.host.authorize("enroll", machine) !== undefined) {
|
|
1814
|
+
fail2("pairing_admin_forbidden");
|
|
1815
|
+
}
|
|
1816
|
+
return this.store.issueEnrollment(machine, ttlMs);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
// src/transport/custody.ts
|
|
1820
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
1821
|
+
function createPairingDelivery2(options) {
|
|
1822
|
+
const timeout = options.timeout_ms ?? 5000;
|
|
1823
|
+
const concurrency = options.concurrency ?? 4;
|
|
1824
|
+
if (!Number.isSafeInteger(timeout) || timeout < 1 || timeout > 30000 || !Number.isSafeInteger(concurrency) || concurrency < 1 || concurrency > 64) {
|
|
1825
|
+
fail2("pairing_limit");
|
|
1826
|
+
}
|
|
1827
|
+
const pending = new Map;
|
|
1828
|
+
let closed = false;
|
|
1829
|
+
async function transfer(machine, operation, issue) {
|
|
1830
|
+
if (closed || pending.size >= concurrency) {
|
|
1831
|
+
fail2("pairing_unavailable");
|
|
1832
|
+
}
|
|
1833
|
+
id2(machine);
|
|
1834
|
+
const deliveryId = randomUUID4();
|
|
1835
|
+
let sink;
|
|
1836
|
+
try {
|
|
1837
|
+
sink = options.authorizeChannel({ machine_id: machine, delivery_id: deliveryId, operation });
|
|
1838
|
+
} catch {
|
|
1839
|
+
fail2("pairing_channel_forbidden");
|
|
1840
|
+
}
|
|
1841
|
+
if (!sink || typeof sink.deliver !== "function" || typeof sink.close !== "function") {
|
|
1842
|
+
fail2("pairing_channel_forbidden");
|
|
1843
|
+
}
|
|
1844
|
+
if (closed) {
|
|
1845
|
+
try {
|
|
1846
|
+
sink.close();
|
|
1847
|
+
} catch {}
|
|
1848
|
+
fail2("pairing_unavailable");
|
|
1849
|
+
}
|
|
1850
|
+
const controller = new AbortController;
|
|
1851
|
+
let rejectAbort;
|
|
1852
|
+
const aborted = new Promise((_, reject) => {
|
|
1853
|
+
rejectAbort = reject;
|
|
1854
|
+
});
|
|
1855
|
+
const closeSink = () => {
|
|
1856
|
+
controller.abort();
|
|
1857
|
+
try {
|
|
1858
|
+
sink.close();
|
|
1859
|
+
} catch {}
|
|
1860
|
+
};
|
|
1861
|
+
const abort = () => {
|
|
1862
|
+
closeSink();
|
|
1863
|
+
rejectAbort(new Error("pairing_delivery_unknown"));
|
|
1864
|
+
};
|
|
1865
|
+
const timer = setTimeout(abort, timeout);
|
|
1866
|
+
pending.set(deliveryId, { timer, abort });
|
|
1867
|
+
let installedDigest;
|
|
1868
|
+
let sending = false;
|
|
1869
|
+
try {
|
|
1870
|
+
const credential = issue();
|
|
1871
|
+
installedDigest = hash2(credential.credential);
|
|
1872
|
+
const generation = credential.recovery_generation;
|
|
1873
|
+
const revision = options.identities.credentialRevision(machine);
|
|
1874
|
+
sending = true;
|
|
1875
|
+
const delivered = Promise.resolve().then(() => sink.deliver(structuredClone(credential), controller.signal, { delivery_id: deliveryId, revision })).finally(() => {
|
|
1876
|
+
clearTimeout(timer);
|
|
1877
|
+
pending.delete(deliveryId);
|
|
1878
|
+
});
|
|
1879
|
+
const ack = await Promise.race([delivered, aborted]);
|
|
1880
|
+
if (!ack || ack.delivery_id !== deliveryId || ack.revision !== revision || ack.machine_id !== machine || ack.recovery_generation !== generation) {
|
|
1881
|
+
fail2("pairing_ack_mismatch");
|
|
1882
|
+
}
|
|
1883
|
+
if (closed || controller.signal.aborted) {
|
|
1884
|
+
fail2("pairing_delivery_unknown");
|
|
1885
|
+
}
|
|
1886
|
+
return { machine_id: machine, delivery_id: deliveryId, state: "delivered" };
|
|
1887
|
+
} catch {
|
|
1888
|
+
if (installedDigest !== undefined) {
|
|
1889
|
+
try {
|
|
1890
|
+
options.identities.rejectDelivery(machine, installedDigest);
|
|
1891
|
+
} catch {}
|
|
1892
|
+
}
|
|
1893
|
+
return fail2("pairing_delivery_unknown");
|
|
1894
|
+
} finally {
|
|
1895
|
+
clearTimeout(timer);
|
|
1896
|
+
closeSink();
|
|
1897
|
+
if (!sending) {
|
|
1898
|
+
pending.delete(deliveryId);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
return {
|
|
1903
|
+
async redeem(request) {
|
|
1904
|
+
if (typeof request.enrollment !== "string" || !/^[A-Za-z0-9_-]{32,256}$/.test(request.enrollment)) {
|
|
1905
|
+
fail2("invalid_enrollment");
|
|
1906
|
+
}
|
|
1907
|
+
return transfer(request.registration_id, "enroll", () => {
|
|
1908
|
+
const device = options.backend.redeem(request.enrollment);
|
|
1909
|
+
if (device.machine_id !== request.registration_id) {
|
|
1910
|
+
fail2("pairing_target_mismatch");
|
|
1911
|
+
}
|
|
1912
|
+
return { ...device, recovery_generation: options.backend.generation() };
|
|
1913
|
+
});
|
|
1914
|
+
},
|
|
1915
|
+
status() {
|
|
1916
|
+
return { closed, pending: pending.size };
|
|
1917
|
+
},
|
|
1918
|
+
close() {
|
|
1919
|
+
if (closed) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
closed = true;
|
|
1923
|
+
for (const item of pending.values()) {
|
|
1924
|
+
clearTimeout(item.timer);
|
|
1925
|
+
item.abort();
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1798
1930
|
// src/transport/lifecycle.ts
|
|
1799
1931
|
function createDeviceLifecycle2(store) {
|
|
1800
1932
|
function authenticate(machine, generation, credential) {
|
|
@@ -1864,6 +1996,6 @@ function createDeviceLifecycleAdapter2(lifecycle, channels, services) {
|
|
|
1864
1996
|
};
|
|
1865
1997
|
return { backend, adapter: createLuvusWireAdapter2(backend) };
|
|
1866
1998
|
}
|
|
1867
|
-
export { closeSession, OFFER, providerHealth, ready, ReceiveWindow, ChannelRegistry2, createGateway2, createConnector2, createDeviceLifecycle2, createDeviceLifecycleAdapter2 };
|
|
1999
|
+
export { closeSession, OFFER, providerHealth, ready, ReceiveWindow, ChannelRegistry2, createGateway2, createConnector2, PairingAdmin2, createPairingDelivery2, createDeviceLifecycle2, createDeviceLifecycleAdapter2 };
|
|
1868
2000
|
|
|
1869
|
-
//# debugId=
|
|
2001
|
+
//# debugId=1F0ADD524CEDDA6964756E2164756E21
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
fail2,
|
|
4
|
+
object2,
|
|
5
|
+
fields2,
|
|
6
|
+
id2,
|
|
7
|
+
boundedJson2
|
|
8
|
+
} from "./chunk-qt9m2kg2.js";
|
|
9
|
+
import {
|
|
10
|
+
privatePath,
|
|
11
|
+
privateFile,
|
|
12
|
+
createPrivate,
|
|
13
|
+
syncParentDirectory
|
|
14
|
+
} from "./chunk-0y5542k8.js";
|
|
15
|
+
|
|
16
|
+
// src/transport/credentials.ts
|
|
17
|
+
import { constants, closeSync, fstatSync, openSync, readFileSync, renameSync, unlinkSync } from "fs";
|
|
18
|
+
import { randomUUID } from "crypto";
|
|
19
|
+
function validate(value) {
|
|
20
|
+
const v = object2(value);
|
|
21
|
+
fields2(v, ["machine_id", "recovery_generation", "credential"]);
|
|
22
|
+
id2(v.machine_id);
|
|
23
|
+
id2(v.recovery_generation);
|
|
24
|
+
if (typeof v.credential !== "string" || !/^[A-Za-z0-9_-]{32,256}$/.test(v.credential)) {
|
|
25
|
+
fail2("invalid_device_credential");
|
|
26
|
+
}
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
function saveCredential2(path, input, replace = false) {
|
|
30
|
+
privatePath(path);
|
|
31
|
+
const raw = boundedJson2(validate(input), 4096);
|
|
32
|
+
if (!replace) {
|
|
33
|
+
createPrivate(path, raw);
|
|
34
|
+
syncParentDirectory(path, true);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
privateFile(path);
|
|
38
|
+
const temporary = path + "." + randomUUID();
|
|
39
|
+
try {
|
|
40
|
+
createPrivate(temporary, raw);
|
|
41
|
+
renameSync(temporary, path);
|
|
42
|
+
syncParentDirectory(path, true);
|
|
43
|
+
} finally {
|
|
44
|
+
try {
|
|
45
|
+
unlinkSync(temporary);
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function createFileCredentialSink2(path, expected, replace = false) {
|
|
50
|
+
privatePath(path);
|
|
51
|
+
id2(expected.machine_id);
|
|
52
|
+
id2(expected.recovery_generation);
|
|
53
|
+
let closed = false;
|
|
54
|
+
let used = false;
|
|
55
|
+
return {
|
|
56
|
+
async deliver(input, signal, context) {
|
|
57
|
+
if (closed || used || signal.aborted) {
|
|
58
|
+
fail2("credential_sink_closed");
|
|
59
|
+
}
|
|
60
|
+
if (input.machine_id !== expected.machine_id || input.recovery_generation !== expected.recovery_generation) {
|
|
61
|
+
fail2("credential_sink_mismatch");
|
|
62
|
+
}
|
|
63
|
+
used = true;
|
|
64
|
+
saveCredential2(path, input, replace);
|
|
65
|
+
return { ...context, machine_id: input.machine_id, recovery_generation: input.recovery_generation };
|
|
66
|
+
},
|
|
67
|
+
close() {
|
|
68
|
+
closed = true;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function loadCredential2(path) {
|
|
73
|
+
privatePath(path);
|
|
74
|
+
privateFile(path);
|
|
75
|
+
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
76
|
+
try {
|
|
77
|
+
const st = fstatSync(fd);
|
|
78
|
+
if (!st.isFile() || st.nlink !== 1 || process.platform !== "win32" && ((st.mode & 511) !== 384 || st.uid !== process.getuid?.()) || st.size > 4096) {
|
|
79
|
+
fail2("unsafe_storage_file");
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
return validate(JSON.parse(readFileSync(fd, "utf8")));
|
|
83
|
+
} catch {
|
|
84
|
+
fail2("invalid_device_credential");
|
|
85
|
+
}
|
|
86
|
+
} finally {
|
|
87
|
+
closeSync(fd);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { saveCredential2, createFileCredentialSink2, loadCredential2 };
|
|
92
|
+
|
|
93
|
+
//# debugId=CE63F3C4843F109E64756E2164756E21
|
|
@@ -931,7 +931,7 @@ function createManagementHandler2(options) {
|
|
|
931
931
|
return failure2("invalid_arguments", 400);
|
|
932
932
|
}
|
|
933
933
|
const context = { ...identity, wait_signal: controller.signal };
|
|
934
|
-
const reply = await options.service.execute(operation, args, context);
|
|
934
|
+
const reply = operation.startsWith("resources/") ? await options.resources.execute(operation.slice("resources/".length), args, identity, controller.signal) : await options.service.execute(operation, args, context);
|
|
935
935
|
if (controller.signal.aborted) {
|
|
936
936
|
return failure2("outcome_unconfirmed", 503);
|
|
937
937
|
}
|
|
@@ -952,7 +952,7 @@ function createManagementHandler2(options) {
|
|
|
952
952
|
} catch {
|
|
953
953
|
return failure2("forbidden", 403);
|
|
954
954
|
}
|
|
955
|
-
if (!url.pathname.startsWith("/admin/v1/actions/")) {
|
|
955
|
+
if (!url.pathname.startsWith("/admin/v1/actions/") && !url.pathname.startsWith("/admin/v1/resources/")) {
|
|
956
956
|
return reads.fetch(request);
|
|
957
957
|
}
|
|
958
958
|
let size = 0;
|
|
@@ -967,7 +967,19 @@ function createManagementHandler2(options) {
|
|
|
967
967
|
if (request.method !== "POST") {
|
|
968
968
|
return failure2("method_not_allowed", 405);
|
|
969
969
|
}
|
|
970
|
-
const
|
|
970
|
+
const resource = url.pathname.startsWith("/admin/v1/resources/") ? url.pathname.slice("/admin/v1/resources/".length) : null;
|
|
971
|
+
const operation = resource !== null && options.resources && [
|
|
972
|
+
"tokens_list",
|
|
973
|
+
"tokens_create",
|
|
974
|
+
"tokens_delete",
|
|
975
|
+
"tokens_rotate",
|
|
976
|
+
"pairing_codes_list",
|
|
977
|
+
"pairing_codes_create",
|
|
978
|
+
"pairing_codes_revoke",
|
|
979
|
+
"pairings_list",
|
|
980
|
+
"pairings_delete",
|
|
981
|
+
"devices_delete"
|
|
982
|
+
].includes(resource) ? `resources/${resource}` : routes.get(url.pathname);
|
|
971
983
|
if (!operation) {
|
|
972
984
|
return failure2("not_found", 404);
|
|
973
985
|
}
|
|
@@ -1184,4 +1196,4 @@ function createManagementSessionAdapter2(options) {
|
|
|
1184
1196
|
}
|
|
1185
1197
|
export { createManagementReadHandler2, startManagementReadListener2, startManagementListener2, loadManagementAssets2, ManagementServiceError2, StoreManagementWriteService2, createManagementHandler2, createManagementSessionAdapter2 };
|
|
1186
1198
|
|
|
1187
|
-
//# debugId=
|
|
1199
|
+
//# debugId=77B098389207C26664756E2164756E21
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
canonical2
|
|
4
4
|
} from "./chunk-d71r315c.js";
|
|
5
|
+
import {
|
|
6
|
+
cliMessages2
|
|
7
|
+
} from "./chunk-pgs9jp6t.js";
|
|
5
8
|
|
|
6
9
|
// src/mcp/schema.ts
|
|
7
10
|
import { Ajv } from "ajv";
|
|
@@ -61,19 +64,9 @@ var schemas = {
|
|
|
61
64
|
runtime_result_read: object({ result_id: id, cursor, max_bytes: { type: "integer", minimum: 1, maximum: MAX_RESULT_BYTES2 } }, ["result_id"]),
|
|
62
65
|
runtime_response_discard: object({ call_id: id }, ["call_id"])
|
|
63
66
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
providers_list: "\u5217\u51FA\u6307\u5B9A\u8BBE\u5907\u4E0B\u5F53\u524D caller \u53EF\u89C1\u7684\u5DF2\u914D\u7F6E provider\uFF1B\u4E0D\u8FD4\u56DE\u672C\u673A\u914D\u7F6E\u3002",
|
|
68
|
-
providers_get: "\u8BFB\u53D6\u663E\u5F0F provider \u7684 kind\u3001revision \u548C readiness\u3002",
|
|
69
|
-
runtime_discover: "\u53D1\u73B0\u663E\u5F0F Target/revision \u7684\u6709\u6548\u80FD\u529B\u53CA\u6765\u6E90\uFF1B\u4E0D\u6388\u4E88\u6267\u884C\u6743\u9650\u3002",
|
|
70
|
-
runtime_describe: "\u63CF\u8FF0\u663E\u5F0F Target/revision \u4E0B\u7CBE\u786E\u65B9\u6CD5\u7684\u539F\u751F\u53C2\u6570\u3001\u5206\u7C7B\u548C\u9650\u5236\u3002",
|
|
71
|
-
runtime_call: "\u63D0\u4EA4\u4E00\u6B21\u663E\u5F0F Target/revision/\u5951\u7EA6\u7684\u539F\u751F\u8C03\u7528\u3002deadline \u662F\u7EDD\u5BF9\u6BEB\u79D2\u671F\u9650\uFF0Cwait_ms \u53EA\u63A7\u5236\u77ED\u7B49\uFF1B\u4E0D\u91CD\u8BD5\u6216\u7BA1\u7406 provider\u3002",
|
|
72
|
-
runtime_call_get: "\u6309\u5F53\u524D\u5F52\u5C5E\u3001\u53CC\u7AEF\u7B56\u7565\u548C\u5185\u5BB9\u95E8\u7981\u8BFB\u53D6\u8C03\u7528\uFF1B\u77ED\u7B49\u5230\u671F\u4E0D\u6539\u53D8\u6267\u884C\u671F\u9650\u3002",
|
|
73
|
-
runtime_call_cancel: "\u8BF7\u6C42\u505C\u6B62\u7B49\u5F85\u6216\u6865\u63A5\uFF1B\u4EC5\u62A5\u544A\u670D\u52A1\u53EF\u786E\u8BA4\u7A0B\u5EA6\uFF0C\u4E0D\u627F\u8BFA\u539F\u751F\u56DE\u6EDA\u3002",
|
|
74
|
-
runtime_result_read: "\u6309\u5F53\u524D\u8BFB\u53D6\u6388\u6743\u548C\u671F\u9650\u8BFB\u53D6\u6709\u754C\u7ED3\u679C\u9875\uFF1Bcursor \u7531\u670D\u52A1\u7ED1\u5B9A caller \u548C\u539F\u7ED3\u679C\u3002",
|
|
75
|
-
runtime_response_discard: "\u5904\u7406\u5B8C\u7ED3\u679C\u540E\u663E\u5F0F\u5220\u9664\u539F\u6587\u4E0E\u53E5\u67C4\u5E76\u91CA\u653E\u8BFB\u53D6\u5BB9\u91CF\uFF1B\u5FC5\u987B\u9A8C\u8BC1\u5F52\u5C5E\u3001\u5F53\u524D\u539F\u65B9\u6CD5\u7B56\u7565\u53CA\u72EC\u7ACB discard_response \u6743\u9650\u3002\u8BFB\u53D6\u5230 EOF \u4E0D\u4F1A\u81EA\u52A8\u5220\u9664\u7ED3\u679C\u3002"
|
|
76
|
-
};
|
|
67
|
+
function toolDescription(name, language = "en") {
|
|
68
|
+
return cliMessages2(language)["mcp.tool." + name];
|
|
69
|
+
}
|
|
77
70
|
var readOnly = new Set([
|
|
78
71
|
"machines_list",
|
|
79
72
|
"machines_get",
|
|
@@ -89,10 +82,10 @@ var validators = new Map(Object.entries(schemas).map(([name, schema]) => [name,
|
|
|
89
82
|
function toolNames2() {
|
|
90
83
|
return Object.keys(schemas);
|
|
91
84
|
}
|
|
92
|
-
function toolDefinition2(name) {
|
|
85
|
+
function toolDefinition2(name, language = "en") {
|
|
93
86
|
return {
|
|
94
87
|
name,
|
|
95
|
-
description:
|
|
88
|
+
description: toolDescription(name, language),
|
|
96
89
|
inputSchema: structuredClone(schemas[name]),
|
|
97
90
|
outputSchema: {
|
|
98
91
|
type: "object",
|
|
@@ -178,4 +171,4 @@ class NativeRequestNotDispatchedError extends FacadeServiceError2 {
|
|
|
178
171
|
|
|
179
172
|
export { MAX_MCP_BYTES2, MAX_RESULT_BYTES2, MAX_WAIT_MS2, TOOLS_PAGE_SIZE, toolNames2, toolDefinition2, isToolName, parseToolArguments2, SERVICE_ERROR_CODES, FacadeServiceError2, NativeRequestNotDispatchedError };
|
|
180
173
|
|
|
181
|
-
//# debugId=
|
|
174
|
+
//# debugId=E037D9DEF799B17A64756E2164756E21
|
|
@@ -14,8 +14,11 @@ import {
|
|
|
14
14
|
assertUsage,
|
|
15
15
|
GATEWAY_LOCK_FORMAT2,
|
|
16
16
|
Store2
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import"./chunk-
|
|
17
|
+
} from "./chunk-av31bx1e.js";
|
|
18
|
+
import"./chunk-vdwzb63d.js";
|
|
19
|
+
import {
|
|
20
|
+
cliMessages2
|
|
21
|
+
} from "./chunk-pgs9jp6t.js";
|
|
19
22
|
import {
|
|
20
23
|
readRuntimeConfig2
|
|
21
24
|
} from "./chunk-bspzg8er.js";
|
|
@@ -33,8 +36,8 @@ import {
|
|
|
33
36
|
import"./chunk-3nnahj0j.js";
|
|
34
37
|
import {
|
|
35
38
|
lockContent
|
|
36
|
-
} from "./chunk-
|
|
37
|
-
import"./chunk-
|
|
39
|
+
} from "./chunk-h3xyq7zk.js";
|
|
40
|
+
import"./chunk-qp8tgms2.js";
|
|
38
41
|
import {
|
|
39
42
|
privatePath,
|
|
40
43
|
databasePath,
|
|
@@ -131,17 +134,6 @@ function inspectStorage(input) {
|
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
// src/cli/storage-command.ts
|
|
134
|
-
var STORAGE_HELP = `\u7528\u6CD5\uFF1A
|
|
135
|
-
rovloom doctor --role gateway|connector [--config /absolute/config.json] [--json]
|
|
136
|
-
rovloom storage check --role gateway [--config /absolute/config.json] [--json]
|
|
137
|
-
rovloom storage backup --role gateway --output /path/to/gateway.backups/snapshot.db [--config /absolute/config.json] [--json]
|
|
138
|
-
rovloom storage resume --role gateway [--config /absolute/config.json] [--json]
|
|
139
|
-
|
|
140
|
-
Gateway \u547D\u4EE4\u987B\u5148\u505C\u6B62\u670D\u52A1\uFF1B\u6CBF\u7528\u540C\u4E00\u5199\u9501\uFF0C\u62D2\u7EDD\u6D3B\u52A8\u6216\u65E0\u6CD5\u5224\u5B9A\u7684\u6301\u6709\u8005\u3002
|
|
141
|
-
check \u53EA\u8BFB\uFF1Bbackup \u4EC5\u4F7F\u7528\u771F\u5B9E\u72B6\u6001\u76EE\u5F55\u540C\u7EA7\u7684 <state>.backups \u666E\u901A\u76EE\u5F55\uFF0C\u5BFC\u51FA\u8131\u654F\u5FEB\u7167\uFF08\u4E0D\u542B\u539F\u6587\u53CA\u6709\u6548\u51ED\u636E\uFF09\uFF0C\u5B8C\u6574\u72B6\u6001\u9700\u53E6\u884C\u79BB\u7EBF\u5907\u4EFD\u3002
|
|
142
|
-
resume \u662F\u672C\u673A\u64CD\u4F5C\u5458\u663E\u5F0F\u6279\u51C6\u7684\u89E3\u9664\u964D\u7EA7\uFF0C\u5B8C\u6574\u6027\u3001\u65F6\u949F\u6216\u9884\u7B97\u4E0D\u6B63\u5E38\u65F6\u4ECD\u62D2\u7EDD\u3002
|
|
143
|
-
Connector doctor \u53EA\u68C0\u67E5\u914D\u7F6E\u53CA managed \u72B6\u6001\uFF0C\u4E0D\u542F\u52A8 native\uFF0C\u4E5F\u4E0D\u58F0\u660E native \u5C31\u7EEA\u3002
|
|
144
|
-
`;
|
|
145
137
|
function parse(args) {
|
|
146
138
|
const action = args[0] === "doctor" ? "doctor" : args[1];
|
|
147
139
|
if (!["doctor", "check", "backup", "resume"].includes(action ?? "")) {
|
|
@@ -201,7 +193,7 @@ async function handleStorageCommand(args, io, environment) {
|
|
|
201
193
|
let json = args.includes("--json");
|
|
202
194
|
try {
|
|
203
195
|
if (args.length === 2 && args[1] === "--help") {
|
|
204
|
-
io.stderr.write(
|
|
196
|
+
io.stderr.write(cliMessages2(io.language)["help.storage"]);
|
|
205
197
|
return 0;
|
|
206
198
|
}
|
|
207
199
|
const flags = parse(args);
|
|
@@ -318,4 +310,4 @@ export {
|
|
|
318
310
|
handleStorageCommand
|
|
319
311
|
};
|
|
320
312
|
|
|
321
|
-
//# debugId=
|
|
313
|
+
//# debugId=2C436BD5D6042D5D64756E2164756E21
|
|
@@ -3,27 +3,6 @@ import {
|
|
|
3
3
|
fail2
|
|
4
4
|
} from "./chunk-qt9m2kg2.js";
|
|
5
5
|
|
|
6
|
-
// src/connector/luvus/types.ts
|
|
7
|
-
class LuvusAdapterError2 extends Error {
|
|
8
|
-
code;
|
|
9
|
-
outcome;
|
|
10
|
-
constructor(code, outcome = "not_dispatched") {
|
|
11
|
-
super(code);
|
|
12
|
-
this.code = code;
|
|
13
|
-
this.outcome = outcome;
|
|
14
|
-
this.name = "LuvusAdapterError";
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// src/connector/capacity.ts
|
|
19
|
-
class ConnectorCapacityError extends LuvusAdapterError2 {
|
|
20
|
-
capacity;
|
|
21
|
-
constructor(resource, reclaimAt) {
|
|
22
|
-
super(resource.startsWith("claim_") ? "claim_capacity" : "connector_attempt_capacity");
|
|
23
|
-
this.capacity = Object.freeze({ resource, reclaim_at: reclaimAt });
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
6
|
// src/connector/local/linux-peer.ts
|
|
28
7
|
import { createRequire } from "module";
|
|
29
8
|
import { Socket } from "net";
|
|
@@ -179,6 +158,6 @@ function assertTerminalExecutionAllowed(kind, request, enabled = false) {
|
|
|
179
158
|
}
|
|
180
159
|
}
|
|
181
160
|
|
|
182
|
-
export {
|
|
161
|
+
export { readLinuxPeer, pinTerminalExecution, terminalExecutionCatalog, assertTerminalExecutionAllowed };
|
|
183
162
|
|
|
184
|
-
//# debugId=
|
|
163
|
+
//# debugId=190A991502F4F00A64756E2164756E21
|
|
@@ -41,7 +41,13 @@ function defaults(role, environment, initialization) {
|
|
|
41
41
|
return { ...config, native: { ...config.native, provider: initialization.provider } };
|
|
42
42
|
}
|
|
43
43
|
if (config.role === "gateway" && initialization.container) {
|
|
44
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
...config,
|
|
46
|
+
mcp_hostname: "0.0.0.0",
|
|
47
|
+
device_hostname: "0.0.0.0",
|
|
48
|
+
management_hostname: "0.0.0.0",
|
|
49
|
+
management_lan: true
|
|
50
|
+
};
|
|
45
51
|
}
|
|
46
52
|
return config;
|
|
47
53
|
}
|
|
@@ -98,4 +104,4 @@ function readOrCreateRoleConfig(role, path, environment, initialization = {}) {
|
|
|
98
104
|
|
|
99
105
|
export { privateDirectory, readOrCreateRoleConfig };
|
|
100
106
|
|
|
101
|
-
//# debugId=
|
|
107
|
+
//# debugId=2B2959D62D3C434064756E2164756E21
|