fix(swarmtop): expose and render full peer identity/details from proc surfaces

This commit is contained in:
Raven Scott
2026-04-26 08:02:37 -04:00
parent 8c3d5f8795
commit 194fbd2c67
69 changed files with 13463 additions and 32 deletions
+34
View File
@@ -57,6 +57,40 @@ const preamble = {
'p2p-suite.js',
'p2p-suite-tui.js'
],
dhttop: [
'edit-ansi.js',
'edit-key-parse.js',
'edit-stream-read.js',
'p2p-suite.js',
'p2p-suite-tui.js'
],
swarmmap: [
'edit-ansi.js',
'edit-key-parse.js',
'edit-stream-read.js',
'p2p-suite.js',
'p2p-suite-tui.js'
],
routeview: [
'edit-ansi.js',
'edit-key-parse.js',
'edit-stream-read.js',
'p2p-suite.js',
'p2p-suite-tui.js'
],
'holepunch-view': [
'edit-ansi.js',
'edit-key-parse.js',
'edit-stream-read.js',
'p2p-suite.js',
'p2p-suite-tui.js'
],
p2ping: ['p2p-suite.js'],
dhtscan: ['p2p-suite.js'],
swarmdoctor: ['p2p-suite.js'],
peerdiscover: ['p2p-suite.js'],
p2ptrace: ['p2p-suite.js'],
peerctl: ['p2p-suite.js'],
meshdrop: ['p2p-suite.js'],
taskmesh: ['p2p-suite.js'],
peernote: ['p2p-suite.js'],
@@ -33,6 +33,8 @@ export const COREUTILS_COMMANDS = [
'dir',
'dirname',
'dircolors',
'dhtscan',
'dhttop',
'du',
'edit',
'echo',
@@ -54,6 +56,7 @@ export const COREUTILS_COMMANDS = [
'hdms',
'help',
'holesail',
'holepunch-view',
'hostid',
'hostname',
'hypershell-board',
@@ -99,6 +102,10 @@ export const COREUTILS_COMMANDS = [
'patch',
'pathchk',
'pathcap-verify',
'p2ping',
'p2ptrace',
'peerctl',
'peerdiscover',
'peernote',
'pr',
'printenv',
@@ -112,6 +119,7 @@ export const COREUTILS_COMMANDS = [
'rev',
'rm',
'rmdir',
'routeview',
'savevault',
'say',
'sed',
@@ -131,6 +139,8 @@ export const COREUTILS_COMMANDS = [
'sshd',
'stat',
'swarmtop',
'swarmdoctor',
'swarmmap',
'sum',
'sync',
'tar',
+28 -1
View File
@@ -208,6 +208,33 @@ async function bareP2pReadSwarmSnapshot(ctx) {
if (typeof snap.peerCount === 'number') out.peerCount = snap.peerCount
if (typeof snap.topicCount === 'number') out.topicCount = snap.topicCount
const peers = Array.isArray(snap.peers) ? snap.peers : []
out.peers = peers.slice(0, 128)
const detailsRaw = await bareP2pReadJson(ctx, '/proc/bare_os/peer_details.json')
const details =
detailsRaw && typeof detailsRaw === 'object' && Array.isArray(detailsRaw.peers)
? detailsRaw.peers
: []
/** @type {Map<string, Record<string, unknown>>} */
const byKey = new Map()
for (const d of details) {
if (!d || typeof d !== 'object') continue
const rk = typeof d.remotePublicKey === 'string' ? d.remotePublicKey : ''
const pid = typeof d.peerId === 'string' ? d.peerId : ''
if (rk) byKey.set('k:' + rk, d)
if (pid) byKey.set('p:' + pid, d)
}
const merged = []
for (const p of peers) {
if (!p || typeof p !== 'object') continue
const rk = typeof p.remotePublicKey === 'string' ? p.remotePublicKey : ''
const pid = typeof p.peerId === 'string' ? p.peerId : ''
const d = (rk && byKey.get('k:' + rk)) || (pid && byKey.get('p:' + pid)) || null
merged.push(d && typeof d === 'object' ? { ...p, ...d } : p)
}
out.peers = merged.slice(0, 128)
return out
}
async function bareP2pReadProcJson(ctx, path) {
const v = await bareP2pReadJson(ctx, path)
return v && typeof v === 'object' ? v : {}
}
@@ -0,0 +1,9 @@
{
"name": "dhtscan",
"section": 1,
"title": "dht scan summary",
"synopsis": ["dhtscan"],
"description": "Reads and prints compact DHT diagnostics from /proc/bare_os/dht_scan.json.",
"options": [],
"keywords": ["p2p", "dht", "diagnostics"]
}
@@ -0,0 +1,9 @@
{
"name": "dhttop",
"section": 1,
"title": "live dht tui",
"synopsis": ["dhttop"],
"description": "TTY dashboard for DHT status and bootstrap/firewall hints.",
"options": [],
"keywords": ["p2p", "dht", "tui"]
}
@@ -0,0 +1,9 @@
{
"name": "holepunch-view",
"section": 1,
"title": "holepunch and nat tui",
"synopsis": ["holepunch-view"],
"description": "Displays NAT and holepunch summary telemetry for the current swarm session.",
"options": [],
"keywords": ["p2p", "nat", "holepunch", "tui"]
}
@@ -0,0 +1,9 @@
{
"name": "p2ping",
"section": 1,
"title": "p2p ping probe",
"synopsis": ["p2ping [LABEL]"],
"description": "Emits a p2p ping event and prints local latency and swarm peer hints.",
"options": [],
"keywords": ["p2p", "ping", "latency", "swarm"]
}
@@ -0,0 +1,9 @@
{
"name": "p2ptrace",
"section": 1,
"title": "p2p trace collector",
"synopsis": ["p2ptrace [APP] [N]"],
"description": "Dumps recent p2p events as JSON lines for tracing and diagnostics.",
"options": [],
"keywords": ["p2p", "trace", "json"]
}
@@ -0,0 +1,9 @@
{
"name": "peerctl",
"section": 1,
"title": "peer control plane utility",
"synopsis": ["peerctl health", "peerctl request ACTION [JSON_PAYLOAD]", "peerctl history [N]"],
"description": "P2P control helper for health checks and request envelopes.",
"options": [],
"keywords": ["p2p", "control", "rpc"]
}
@@ -0,0 +1,9 @@
{
"name": "peerdiscover",
"section": 1,
"title": "peer service discovery utility",
"synopsis": ["peerdiscover announce SERVICE [META]", "peerdiscover list [N]"],
"description": "Announces and lists peer service metadata over p2p event history.",
"options": [],
"keywords": ["p2p", "discovery", "service"]
}
@@ -0,0 +1,9 @@
{
"name": "routeview",
"section": 1,
"title": "route visibility tui",
"synopsis": ["routeview"],
"description": "Shows direct-vs-relay route summary from /proc/bare_os/route_summary.json.",
"options": [],
"keywords": ["p2p", "routing", "relay", "tui"]
}
@@ -0,0 +1,9 @@
{
"name": "swarmdoctor",
"section": 1,
"title": "swarm diagnostic doctor",
"synopsis": ["swarmdoctor"],
"description": "Reads /proc/bare_os/swarm_doctor.json and reports swarm health/remediation.",
"options": [],
"keywords": ["p2p", "swarm", "doctor"]
}
@@ -0,0 +1,9 @@
{
"name": "swarmmap",
"section": 1,
"title": "swarm topology map tui",
"synopsis": ["swarmmap"],
"description": "Live peer topology viewer for swarm peers and states.",
"options": [],
"keywords": ["p2p", "swarm", "tui", "topology"]
}
+1 -1
View File
@@ -6,6 +6,6 @@
"description": "Build JS /bin utilities for bare-operating-system (concat + stage to kernel/)",
"scripts": {
"build": "node ./scripts/ensure-man-pages.mjs && node ./build.mjs",
"test": "node ./test/clear-sequence.test.mjs && node ./test/help-bin-list.test.mjs && node ./test/whois-rdap.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baresay-say-bundle.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/baretop-compose.test.mjs && node ./test/baretop-incremental.test.mjs && node ./test/baretop-ui-helpers.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs && node ./test/expand-tab-stops.test.mjs && node ./test/pkg-swarm-index-pathcap.test.mjs && node ./test/sha224-sha384-sum.test.mjs && node ./test/agent-sse-parse.test.mjs && node ./test/agent-web-fetch.test.mjs && node ./test/agent-helpers.test.mjs && node ./test/agent-workspace.test.mjs && node ./test/agent-skills.test.mjs && node ./test/agent-config-surface.test.mjs && node ./test/telnet-protocol.test.mjs && node ./test/telnet-cli.test.mjs && node ./test/login.test.mjs && node ./test/p2p-suite-bundles.test.mjs"
"test": "node ./test/clear-sequence.test.mjs && node ./test/help-bin-list.test.mjs && node ./test/whois-rdap.test.mjs && node ./test/edit-key-parse.test.mjs && node ./test/edit-teardown.test.mjs && node ./test/baresay-say-bundle.test.mjs && node ./test/baretop-bundle.test.mjs && node ./test/baretop-fixture.test.mjs && node ./test/baretop-compose.test.mjs && node ./test/baretop-incremental.test.mjs && node ./test/baretop-ui-helpers.test.mjs && node ./test/posix-test-int-compare.test.mjs && node ./test/posix-utils-edge.test.mjs && node ./test/posix-golden-issue7.test.mjs && node ./test/getconf-pathconf-union-mirror.test.mjs && node ./test/getconf-posix-shm.test.mjs && node ./test/awk-sed-posix-smoke.test.mjs && node ./test/xattr-acl-utils.test.mjs && node ./test/xcu-issue7-sweep.test.mjs && node ./test/expand-tab-stops.test.mjs && node ./test/pkg-swarm-index-pathcap.test.mjs && node ./test/sha224-sha384-sum.test.mjs && node ./test/agent-sse-parse.test.mjs && node ./test/agent-web-fetch.test.mjs && node ./test/agent-helpers.test.mjs && node ./test/agent-workspace.test.mjs && node ./test/agent-skills.test.mjs && node ./test/agent-config-surface.test.mjs && node ./test/telnet-protocol.test.mjs && node ./test/telnet-cli.test.mjs && node ./test/login.test.mjs && node ./test/p2p-suite-bundles.test.mjs && node ./test/swarmtop-peer-visibility.test.mjs"
}
}
+16
View File
@@ -0,0 +1,16 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'dhtscan'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' +
argv0 +
'\n' +
'Print compact DHT scan summary from /proc/bare_os/dht_scan.json.\n' +
'See man dhtscan.'
)
return
}
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
ctx.console.log(JSON.stringify(dht, null, 2))
}
+34
View File
@@ -0,0 +1,34 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'dhttop'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' + argv0 + '\n' + 'Live DHT dashboard TUI.\n' + 'See man dhttop.'
)
return
}
const stdin = ctx.replStdin
const isTTY = Boolean(stdin && /** @type {{ isTTY?: boolean }} */ (stdin).isTTY)
if (!isTTY) {
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
ctx.console.log(JSON.stringify(dht, null, 2))
return
}
await bareP2pRunSimpleTui(ctx, {
title: 'dhttop',
subtitle: 'dht operations · q quit · r refresh',
renderLines: async () => {
const dht = await bareP2pReadProcJson(ctx, '/proc/bare_os/dht_scan.json')
const lines = []
lines.push('schema: ' + String(dht.schema ?? '?'))
lines.push('peers: ' + String(dht.peers ?? '?'))
lines.push('firewalled: ' + String(dht.dhtStatus?.firewalled ?? '?'))
lines.push('randomized: ' + String(dht.dhtStatus?.randomized ?? '?'))
lines.push('bootstrap: ' + String(dht.bootstrapHint || '(default)'))
lines.push('')
lines.push('raw:')
lines.push(JSON.stringify(dht))
return lines
}
})
}
@@ -0,0 +1,35 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'holepunch-view'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' +
argv0 +
'\n' +
'NAT and holepunch summary dashboard.\n' +
'See man holepunch-view.'
)
return
}
const stdin = ctx.replStdin
const isTTY = Boolean(stdin && /** @type {{ isTTY?: boolean }} */ (stdin).isTTY)
if (!isTTY) {
const h = await bareP2pReadProcJson(ctx, '/proc/bare_os/holepunch_summary.json')
ctx.console.log(JSON.stringify(h, null, 2))
return
}
await bareP2pRunSimpleTui(ctx, {
title: 'holepunch-view',
subtitle: 'nat and holepunch telemetry · q quit · r refresh',
renderLines: async () => {
const h = await bareP2pReadProcJson(ctx, '/proc/bare_os/holepunch_summary.json')
return [
'peers: ' + String(h.peers ?? '?'),
'firewalled: ' + String(h.firewalled ?? '?'),
'randomized: ' + String(h.randomized ?? '?'),
'',
'note: ' + String(h.note || '')
]
}
})
}
+36
View File
@@ -0,0 +1,36 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'p2ping'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' +
argv0 +
' [LABEL]\n' +
'Emit a p2p ping event and print local swarm timing hints.\n' +
'See man p2ping.'
)
return
}
const label = args.join(' ').trim() || 'ping'
const t0 = Date.now()
const swarm = await bareP2pReadSwarmSnapshot(ctx)
const evtId = bareP2pId('p2ping')
const send = bareP2pSend(ctx, 'p2ping', 'ping', {
evtId,
label,
sentAtMs: t0
})
const t1 = Date.now()
const out = {
schema: 1,
tool: argv0,
evtId,
label,
ok: !(send && send.ok === false),
sendReason: send && send.ok === false ? String(send.reason || 'send_failed') : null,
localElapsedMs: t1 - t0,
swarmPeers: swarm.peerCount
}
ctx.console.log(JSON.stringify(out, null, 2))
if (send && send.ok === false) ctx.exitCode = 1
}
@@ -0,0 +1,45 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'p2ptrace'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' +
argv0 +
' [APP] [N]\n' +
'Dump recent p2p events as JSON lines.\n' +
'APP defaults to all known p2p apps.\n' +
'See man p2ptrace.'
)
return
}
const app = String(args[0] || '').trim()
const n = Math.max(1, Math.min(2000, parseInt(args[1] || '200', 10) || 200))
const apps = app
? [app]
: [
'swarmtop',
'meshdrop',
'taskmesh',
'peernote',
'hypershell-board',
'p2ping',
'peerdiscover',
'peerctl'
]
const rows = []
for (const a of apps) {
rows.push(...bareP2pCollectFromHistory(ctx, a, n))
}
rows.sort((a, b) => (a.receivedAtMs || 0) - (b.receivedAtMs || 0))
for (const r of rows.slice(-n)) {
ctx.console.log(
JSON.stringify({
atMs: r.receivedAtMs || 0,
app: r.packet?.app || '?',
kind: r.packet?.kind || '?',
from: r.displayName || r.fromPeerKey || '',
payload: r.packet?.payload || {}
})
)
}
}
+81
View File
@@ -0,0 +1,81 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'peerctl'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help') || args.length === 0) {
ctx.console.log(
'usage: ' +
argv0 +
' health\n' +
' ' +
argv0 +
' request ACTION [JSON_PAYLOAD]\n' +
' ' +
argv0 +
' history [N]\n' +
'P2P control plane helper over event envelopes.\n' +
'See man peerctl.'
)
if (args.length === 0) ctx.exitCode = 1
return
}
const sub = args[0]
if (sub === 'health') {
const swarm = await bareP2pReadSwarmSnapshot(ctx)
const doctor = await bareP2pReadProcJson(ctx, '/proc/bare_os/swarm_doctor.json')
ctx.console.log(
JSON.stringify(
{
schema: 1,
swarmPeers: swarm.peerCount,
health: doctor.health || 'unknown',
remediation: doctor.remediation || []
},
null,
2
)
)
return
}
if (sub === 'request') {
const action = String(args[1] || '').trim()
if (!action) {
ctx.console.error(argv0 + ': request requires ACTION')
ctx.exitCode = 1
return
}
let payload = {}
if (args[2]) {
try {
payload = JSON.parse(args.slice(2).join(' '))
} catch {
ctx.console.error(argv0 + ': invalid JSON payload')
ctx.exitCode = 1
return
}
}
const r = bareP2pSend(ctx, 'peerctl', 'request', {
requestId: bareP2pId('ctl'),
action,
payload
})
if (r && r.ok === false) ctx.exitCode = 1
return
}
if (sub === 'history') {
const n = Math.max(1, Math.min(1000, parseInt(args[1] || '50', 10) || 50))
const rows = bareP2pCollectFromHistory(ctx, 'peerctl', 2000).slice(-n)
for (const row of rows) {
ctx.console.log(
'[' +
bareP2pFmtClock(row.receivedAtMs) +
'] ' +
String(row.packet?.kind || '?') +
' ' +
JSON.stringify(row.packet?.payload || {})
)
}
return
}
ctx.console.error(argv0 + ': unsupported subcommand')
ctx.exitCode = 1
}
@@ -0,0 +1,54 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'peerdiscover'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help') || args.length === 0) {
ctx.console.log(
'usage: ' +
argv0 +
' announce SERVICE [META]\n' +
' ' +
argv0 +
' list [N]\n' +
'Peer service announce/list over p2p event history.\n' +
'See man peerdiscover.'
)
if (args.length === 0) ctx.exitCode = 1
return
}
const sub = args[0]
if (sub === 'announce') {
const service = String(args[1] || '').trim()
if (!service) {
ctx.console.error(argv0 + ': announce requires SERVICE')
ctx.exitCode = 1
return
}
const meta = args.slice(2).join(' ').trim()
const r = bareP2pSend(ctx, 'peerdiscover', 'service.announce', {
service,
meta,
id: bareP2pId('svc')
})
if (r && r.ok === false) ctx.exitCode = 1
return
}
if (sub === 'list') {
const n = Math.max(1, Math.min(500, parseInt(args[1] || '50', 10) || 50))
const rows = bareP2pCollectFromHistory(ctx, 'peerdiscover', 2000)
.filter((r) => r.packet?.kind === 'service.announce')
.slice(-n)
for (const row of rows) {
const p = row.packet?.payload || {}
ctx.console.log(
'[' +
bareP2pFmtClock(row.receivedAtMs) +
'] ' +
String(p.service || 'unknown') +
(p.meta ? ' ' + String(p.meta) : '')
)
}
return
}
ctx.console.error(argv0 + ': unsupported subcommand')
ctx.exitCode = 1
}
@@ -0,0 +1,31 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'routeview'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' + argv0 + '\n' + 'Route and relay visibility TUI.\n' + 'See man routeview.'
)
return
}
const stdin = ctx.replStdin
const isTTY = Boolean(stdin && /** @type {{ isTTY?: boolean }} */ (stdin).isTTY)
if (!isTTY) {
const r = await bareP2pReadProcJson(ctx, '/proc/bare_os/route_summary.json')
ctx.console.log(JSON.stringify(r, null, 2))
return
}
await bareP2pRunSimpleTui(ctx, {
title: 'routeview',
subtitle: 'direct vs relay summary · q quit · r refresh',
renderLines: async () => {
const r = await bareP2pReadProcJson(ctx, '/proc/bare_os/route_summary.json')
return [
'peers: ' + String(r.peers ?? '?'),
'directLikely: ' + String(r.directLikely ?? '?'),
'relayLikely: ' + String(r.relayLikely ?? '?'),
'',
'note: ' + String(r.note || '')
]
}
})
}
@@ -0,0 +1,19 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'swarmdoctor'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' +
argv0 +
'\n' +
'Print swarm diagnosis from /proc/bare_os/swarm_doctor.json.\n' +
'See man swarmdoctor.'
)
return
}
const doc = await bareP2pReadProcJson(ctx, '/proc/bare_os/swarm_doctor.json')
ctx.console.log(JSON.stringify(doc, null, 2))
if (doc && typeof doc === 'object' && doc.health && doc.health !== 'ok') {
ctx.exitCode = 1
}
}
@@ -0,0 +1,39 @@
async function run(ctx, argv) {
const argv0 = argv[0] || 'swarmmap'
const args = argv.slice(1)
if (args.includes('-h') || args.includes('--help')) {
ctx.console.log(
'usage: ' + argv0 + '\n' + 'Swarm topology map TUI.\n' + 'See man swarmmap.'
)
return
}
const stdin = ctx.replStdin
const isTTY = Boolean(stdin && /** @type {{ isTTY?: boolean }} */ (stdin).isTTY)
const snap = await bareP2pReadSwarmSnapshot(ctx)
if (!isTTY) {
ctx.console.log(JSON.stringify(snap, null, 2))
return
}
await bareP2pRunSimpleTui(ctx, {
title: 'swarmmap',
subtitle: 'peer topology · q quit · r refresh',
renderLines: async () => {
const s = await bareP2pReadSwarmSnapshot(ctx)
const lines = []
lines.push('peerCount: ' + String(s.peerCount ?? '?'))
lines.push('topicCount: ' + String(s.topicCount ?? '?'))
lines.push('')
lines.push('Peers:')
const peers = Array.isArray(s.peers) ? s.peers : []
if (!peers.length) lines.push(' (none)')
for (const p of peers.slice(0, 48)) {
const id =
p && typeof p === 'object' && typeof p.remotePublicKey === 'string'
? p.remotePublicKey.slice(0, 20)
: '?'
lines.push(' ' + id + ' ' + String(p.state || 'connected'))
}
return lines
}
})
}
+18 -3
View File
@@ -85,16 +85,31 @@ async function run(ctx, argv) {
lines.push('Peers:')
const peers = Array.isArray(snap.peers) ? snap.peers : []
if (!peers.length) lines.push(' (no peers reported)')
for (const p of peers.slice(0, 24)) {
for (const p of peers.slice(0, 12)) {
const key =
p && typeof p === 'object' && typeof p.remotePublicKey === 'string'
? p.remotePublicKey.slice(0, 16)
? p.remotePublicKey
: '?'
const state =
p && typeof p === 'object' && typeof p.state === 'string'
? p.state
: 'connected'
lines.push(' ' + key + ' ' + state)
const addr =
p && typeof p === 'object' && p.endpoint && typeof p.endpoint === 'object'
? String(p.endpoint.address || p.remoteAddress || '?') +
':' +
String(p.endpoint.port || p.remotePort || '?')
: String(p?.remoteAddress || '?') + ':' + String(p?.remotePort || '?')
const osHint =
p &&
typeof p === 'object' &&
p.peerOs &&
typeof p.peerOs === 'object' &&
p.peerOs.osHint
? String(p.peerOs.osHint)
: 'unknown'
lines.push(' pubkey: ' + key)
lines.push(' state=' + state + ' endpoint=' + addr + ' os=' + osHint)
}
lines.push('')
lines.push('Recent events:')
@@ -17,7 +17,17 @@ test('p2p suite commands include shared envelope helper in kernel bins', async (
'meshdrop',
'taskmesh',
'peernote',
'hypershell-board'
'hypershell-board',
'p2ping',
'dhtscan',
'dhttop',
'swarmdoctor',
'swarmmap',
'peerdiscover',
'p2ptrace',
'peerctl',
'routeview',
'holepunch-view'
]
for (const name of names) {
const src = await read(join(kernelBin, name))
@@ -32,7 +42,17 @@ test('p2p suite man pages exist', async (t) => {
'meshdrop',
'taskmesh',
'peernote',
'hypershell-board'
'hypershell-board',
'p2ping',
'dhtscan',
'dhttop',
'swarmdoctor',
'swarmmap',
'peerdiscover',
'p2ptrace',
'peerctl',
'routeview',
'holepunch-view'
]
for (const page of pages) {
const body = await read(join(coreutilsRoot, 'man/pages', page + '.json'))
@@ -0,0 +1,23 @@
import test from 'brittle'
import { readFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const coreutilsRoot = join(__dirname, '..')
test('p2p suite reads peer_details proc for swarm snapshots', async (t) => {
const src = await readFile(join(coreutilsRoot, 'lib/p2p-suite.js'), 'utf8')
t.ok(src.includes('/proc/bare_os/peer_details.json'), 'reads peer details proc')
t.ok(src.includes('out.peers = merged.slice(0, 128)'), 'merges swarm + peer details rows')
})
test('swarmtop renders full public keys and endpoint details', async (t) => {
const src = await readFile(join(coreutilsRoot, 'src/swarmtop.js'), 'utf8')
t.ok(src.includes("lines.push(' pubkey: ' + key)"), 'shows full pubkey label')
t.ok(src.includes('endpoint='), 'shows endpoint details')
t.ok(
src.includes('? p.remotePublicKey') || src.includes('? p.remotePublicKey\n'),
'uses full remotePublicKey value in peer rows'
)
})