forge-memory 0.2.111 → 0.2.112
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 +3 -2
- package/bin/forge-memory.mjs +59 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,8 +40,9 @@ show up as a tool result instead of a closed MCP transport.
|
|
|
40
40
|
`pair-ios` prefers the Iroh QR. Forge starts a Rust Iroh host, prints a QR payload
|
|
41
41
|
with the desktop node id, pairing token, optional relay hint, and ALPN
|
|
42
42
|
`forge-companion/1`, and the iPhone app connects through its native Rust bridge. The
|
|
43
|
-
CLI renders a
|
|
44
|
-
`~/.forge/pairing/` so you can paste it into the iPhone
|
|
43
|
+
CLI renders a short-schema QR to keep the terminal code scannable and saves the
|
|
44
|
+
full manual payload under `~/.forge/pairing/` so you can paste it into the iPhone
|
|
45
|
+
app if the camera cannot scan.
|
|
45
46
|
Use `--manual-http` only when you intentionally want a LAN, Tailscale, or direct
|
|
46
47
|
HTTP/TCP route. For a real iPhone, pass a phone-reachable URL:
|
|
47
48
|
|
package/bin/forge-memory.mjs
CHANGED
|
@@ -1766,6 +1766,48 @@ function compactPairingPayload(payload) {
|
|
|
1766
1766
|
});
|
|
1767
1767
|
}
|
|
1768
1768
|
|
|
1769
|
+
function compactQrPairingPayload(payload) {
|
|
1770
|
+
const manualPayload = compactPairingPayload(payload);
|
|
1771
|
+
const transport = manualPayload.transport
|
|
1772
|
+
? compactObject({
|
|
1773
|
+
p: manualPayload.transport.protocol,
|
|
1774
|
+
d: manualPayload.transport.provider,
|
|
1775
|
+
s: manualPayload.transport.status,
|
|
1776
|
+
pb: manualPayload.transport.publicBaseUrl,
|
|
1777
|
+
lb: manualPayload.transport.localBaseUrl,
|
|
1778
|
+
n: manualPayload.transport.nodeId,
|
|
1779
|
+
r: manualPayload.transport.relay,
|
|
1780
|
+
a: manualPayload.transport.alpn,
|
|
1781
|
+
g: manualPayload.transport.agent,
|
|
1782
|
+
pp: manualPayload.transport.pairPayload
|
|
1783
|
+
? compactObject({
|
|
1784
|
+
v: manualPayload.transport.pairPayload.v,
|
|
1785
|
+
n:
|
|
1786
|
+
manualPayload.transport.pairPayload.node_id ??
|
|
1787
|
+
manualPayload.transport.pairPayload.nodeId,
|
|
1788
|
+
t: manualPayload.transport.pairPayload.token,
|
|
1789
|
+
h:
|
|
1790
|
+
manualPayload.transport.pairPayload.host_name ??
|
|
1791
|
+
manualPayload.transport.pairPayload.hostName,
|
|
1792
|
+
r: manualPayload.transport.pairPayload.relay
|
|
1793
|
+
})
|
|
1794
|
+
: undefined,
|
|
1795
|
+
le: manualPayload.transport.lastError
|
|
1796
|
+
})
|
|
1797
|
+
: undefined;
|
|
1798
|
+
return compactObject({
|
|
1799
|
+
k: "fcp1",
|
|
1800
|
+
a: manualPayload.apiBaseUrl,
|
|
1801
|
+
u: manualPayload.uiBaseUrl,
|
|
1802
|
+
m: manualPayload.transportMode,
|
|
1803
|
+
t: transport,
|
|
1804
|
+
s: manualPayload.sessionId,
|
|
1805
|
+
pt: manualPayload.pairingToken,
|
|
1806
|
+
e: manualPayload.expiresAt,
|
|
1807
|
+
c: manualPayload.capabilities
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1769
1811
|
function compactObject(value) {
|
|
1770
1812
|
if (Array.isArray(value)) {
|
|
1771
1813
|
const compacted = value.map((entry) => compactObject(entry)).filter((entry) => entry !== undefined);
|
|
@@ -1805,27 +1847,28 @@ function isLoopbackPairingUrl(value) {
|
|
|
1805
1847
|
}
|
|
1806
1848
|
|
|
1807
1849
|
async function printPairing(pairing) {
|
|
1808
|
-
const
|
|
1809
|
-
const
|
|
1850
|
+
const manualPayload = compactPairingPayload(pairing.qrPayload);
|
|
1851
|
+
const qrPayload = compactQrPairingPayload(pairing.qrPayload);
|
|
1852
|
+
const qrPayloadText = JSON.stringify(qrPayload);
|
|
1810
1853
|
const terminalColumns = process.stdout.columns ?? 120;
|
|
1811
|
-
if (terminalColumns >= 72 &&
|
|
1854
|
+
if (terminalColumns >= 72 && qrPayloadText.length <= 1_500) {
|
|
1812
1855
|
console.log("\nScan this compact QR in Forge Companion:\n");
|
|
1813
|
-
qrcode.generate(
|
|
1856
|
+
qrcode.generate(qrPayloadText, { small: true });
|
|
1814
1857
|
} else {
|
|
1815
1858
|
console.log("");
|
|
1816
1859
|
console.log(color.yellow("QR skipped because the terminal is too narrow or the payload is too large to scan reliably."));
|
|
1817
1860
|
console.log("Use Manual connection in the iPhone app and paste the saved payload below.");
|
|
1818
1861
|
}
|
|
1819
|
-
const transport =
|
|
1862
|
+
const transport = manualPayload.transport;
|
|
1820
1863
|
if (transport?.provider) {
|
|
1821
1864
|
const label =
|
|
1822
|
-
|
|
1865
|
+
manualPayload.transport?.protocol === "iroh"
|
|
1823
1866
|
? "Iroh"
|
|
1824
|
-
:
|
|
1867
|
+
: manualPayload.transportMode === "iroh"
|
|
1825
1868
|
? "Iroh"
|
|
1826
1869
|
: "Manual HTTP";
|
|
1827
|
-
console.log(`${color.cyan(label)}: ${
|
|
1828
|
-
if (label === "Manual HTTP" && isLoopbackPairingUrl(
|
|
1870
|
+
console.log(`${color.cyan(label)}: ${manualPayload.apiBaseUrl}`);
|
|
1871
|
+
if (label === "Manual HTTP" && isLoopbackPairingUrl(manualPayload.apiBaseUrl)) {
|
|
1829
1872
|
console.log(
|
|
1830
1873
|
color.yellow(
|
|
1831
1874
|
"Manual HTTP points at this machine's loopback address. That is only useful for the iOS Simulator; a real iPhone needs Iroh, Tailscale, or a LAN URL passed with --public-url."
|
|
@@ -1837,7 +1880,7 @@ async function printPairing(pairing) {
|
|
|
1837
1880
|
}
|
|
1838
1881
|
}
|
|
1839
1882
|
try {
|
|
1840
|
-
const filePath = await writePairingPayloadFile(
|
|
1883
|
+
const filePath = await writePairingPayloadFile(manualPayload);
|
|
1841
1884
|
console.log("");
|
|
1842
1885
|
console.log(color.bold("If the QR is too large or the camera will not scan:"));
|
|
1843
1886
|
console.log("1. Open Manual connection in the iPhone app.");
|
|
@@ -1845,14 +1888,18 @@ async function printPairing(pairing) {
|
|
|
1845
1888
|
console.log(`3. Paste the payload saved at: ${filePath}`);
|
|
1846
1889
|
console.log(color.dim(` cat ${filePath}`));
|
|
1847
1890
|
console.log("");
|
|
1848
|
-
console.log(
|
|
1891
|
+
console.log(
|
|
1892
|
+
color.dim(
|
|
1893
|
+
`QR payload bytes: ${qrPayloadText.length}; manual payload bytes: ${JSON.stringify(manualPayload).length}`
|
|
1894
|
+
)
|
|
1895
|
+
);
|
|
1849
1896
|
} catch (error) {
|
|
1850
1897
|
console.log(
|
|
1851
1898
|
color.yellow(
|
|
1852
1899
|
`Could not save pairing payload file: ${error instanceof Error ? error.message : String(error)}`
|
|
1853
1900
|
)
|
|
1854
1901
|
);
|
|
1855
|
-
console.log(
|
|
1902
|
+
console.log(JSON.stringify(manualPayload));
|
|
1856
1903
|
}
|
|
1857
1904
|
}
|
|
1858
1905
|
|
package/package.json
CHANGED