@dmsdc-ai/aigentry-telepty 0.5.8 → 0.6.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 +82 -0
- package/cli.js +392 -30
- package/cross-machine.js +124 -1
- package/daemon-control.js +9 -0
- package/daemon.js +415 -17
- package/install.js +367 -62
- package/package.json +5 -5
- package/src/audit/inject-log.js +234 -0
- package/src/protocol/http-auth.js +36 -1
- package/src/submit-gate.js +130 -5
- package/src/transport/broker-client.js +498 -0
- package/src/transport/broker-protocol.js +155 -0
- package/src/transport/broker-server.js +505 -0
- package/src/win-resolve-executable.js +6 -1
package/cross-machine.js
CHANGED
|
@@ -8,6 +8,7 @@ const { getSharedContextPromptPath } = require('./shared-context');
|
|
|
8
8
|
const { parseHostSpec } = require('./host-spec');
|
|
9
9
|
|
|
10
10
|
const PEERS_PATH = path.join(os.homedir(), '.telepty', 'peers.json');
|
|
11
|
+
const BROKER_CONFIG_PATH = path.join(os.homedir(), '.telepty', 'broker.json');
|
|
11
12
|
const CONTROL_DIR = path.join(os.homedir(), '.telepty', 'ssh');
|
|
12
13
|
|
|
13
14
|
function getPeerTransport(entry) {
|
|
@@ -34,6 +35,30 @@ function savePeers(data) {
|
|
|
34
35
|
} catch {}
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
function normalizeBrokerUrl(url) {
|
|
39
|
+
const value = String(url || '').trim();
|
|
40
|
+
if (!value) return '';
|
|
41
|
+
try {
|
|
42
|
+
const parsed = new URL(value);
|
|
43
|
+
return parsed.toString().replace(/\/+$/, '');
|
|
44
|
+
} catch {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function loadBrokerConfig() {
|
|
50
|
+
try {
|
|
51
|
+
if (!fs.existsSync(BROKER_CONFIG_PATH)) return null;
|
|
52
|
+
return JSON.parse(fs.readFileSync(BROKER_CONFIG_PATH, 'utf8'));
|
|
53
|
+
} catch { return null; }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function saveBrokerConfig(config) {
|
|
57
|
+
fs.mkdirSync(path.dirname(BROKER_CONFIG_PATH), { recursive: true });
|
|
58
|
+
fs.writeFileSync(BROKER_CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
59
|
+
try { fs.chmodSync(BROKER_CONFIG_PATH, 0o600); } catch {}
|
|
60
|
+
}
|
|
61
|
+
|
|
37
62
|
// In-memory active peers
|
|
38
63
|
const activePeers = new Map(); // name -> { target, controlSocket, connectedAt, machineId }
|
|
39
64
|
|
|
@@ -469,6 +494,97 @@ async function discoverHttpRemoteSessions(options = {}) {
|
|
|
469
494
|
return results.flat();
|
|
470
495
|
}
|
|
471
496
|
|
|
497
|
+
// ── Broker peer support (opt-in relay discovery) ────────────────────────────
|
|
498
|
+
// connect-broker stores the node's broker credentials in broker.json (0600) and
|
|
499
|
+
// records a non-secret transport='broker' peer in peers.json. Discovery remains
|
|
500
|
+
// default-OFF: no broker peer entry means list discovery never calls the broker.
|
|
501
|
+
|
|
502
|
+
async function connectBroker(url, options = {}) {
|
|
503
|
+
const brokerUrl = normalizeBrokerUrl(url);
|
|
504
|
+
if (!brokerUrl) {
|
|
505
|
+
return { success: false, error: 'connect-broker requires a valid broker URL.' };
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const node = String(options.node || '').trim();
|
|
509
|
+
if (!node) {
|
|
510
|
+
return { success: false, error: 'connect-broker requires --node <name>.' };
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const jwt = String(options.jwt || '').trim();
|
|
514
|
+
if (!jwt) {
|
|
515
|
+
return { success: false, error: 'connect-broker requires a node JWT.' };
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const connectedAt = new Date().toISOString();
|
|
519
|
+
const config = {
|
|
520
|
+
url: brokerUrl,
|
|
521
|
+
node,
|
|
522
|
+
jwt,
|
|
523
|
+
pin: options.pin || null,
|
|
524
|
+
accept_from: null
|
|
525
|
+
};
|
|
526
|
+
saveBrokerConfig(config);
|
|
527
|
+
|
|
528
|
+
const peers = loadPeers();
|
|
529
|
+
peers.peers[node] = {
|
|
530
|
+
transport: 'broker',
|
|
531
|
+
node,
|
|
532
|
+
url: brokerUrl,
|
|
533
|
+
machineId: node,
|
|
534
|
+
lastConnected: connectedAt
|
|
535
|
+
};
|
|
536
|
+
savePeers(peers);
|
|
537
|
+
|
|
538
|
+
return { success: true, name: node, node, url: brokerUrl };
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function listBrokerPeers() {
|
|
542
|
+
const peers = loadPeers().peers || {};
|
|
543
|
+
return Object.entries(peers)
|
|
544
|
+
.filter(([, entry]) => getPeerTransport(entry) === 'broker')
|
|
545
|
+
.map(([name, entry]) => ({
|
|
546
|
+
name,
|
|
547
|
+
node: entry.node || entry.machineId || name,
|
|
548
|
+
url: entry.url,
|
|
549
|
+
machineId: entry.machineId || entry.node || name,
|
|
550
|
+
lastConnected: entry.lastConnected
|
|
551
|
+
}));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
async function listBrokerRemoteSessions(options = {}) {
|
|
555
|
+
const config = options.config || loadBrokerConfig();
|
|
556
|
+
const brokerUrl = normalizeBrokerUrl(options.url || (config && config.url));
|
|
557
|
+
const jwt = String(options.jwt || (config && config.jwt) || '').trim();
|
|
558
|
+
if (!brokerUrl || !jwt) return [];
|
|
559
|
+
|
|
560
|
+
try {
|
|
561
|
+
const res = await fetch(`${brokerUrl}/broker/sessions`, {
|
|
562
|
+
signal: AbortSignal.timeout(options.timeoutMs || 3000),
|
|
563
|
+
headers: { Authorization: `Bearer ${jwt}` }
|
|
564
|
+
});
|
|
565
|
+
if (!res.ok) return [];
|
|
566
|
+
const body = await res.json();
|
|
567
|
+
const sessions = Array.isArray(body) ? body : body && body.sessions;
|
|
568
|
+
if (!Array.isArray(sessions)) return [];
|
|
569
|
+
return sessions.map((session) => {
|
|
570
|
+
const base = (session && typeof session === 'object') ? session : { id: session };
|
|
571
|
+
const node = base.peerName || base.host || base.node || base.machineId || base.machine_id;
|
|
572
|
+
return {
|
|
573
|
+
...base,
|
|
574
|
+
host: node,
|
|
575
|
+
peerName: node
|
|
576
|
+
};
|
|
577
|
+
});
|
|
578
|
+
} catch {
|
|
579
|
+
return [];
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
async function discoverBrokerRemoteSessions(options = {}) {
|
|
584
|
+
if (listBrokerPeers().length === 0) return [];
|
|
585
|
+
return listBrokerRemoteSessions(options);
|
|
586
|
+
}
|
|
587
|
+
|
|
472
588
|
module.exports = {
|
|
473
589
|
connect,
|
|
474
590
|
disconnect,
|
|
@@ -490,9 +606,16 @@ module.exports = {
|
|
|
490
606
|
listHttpPeers,
|
|
491
607
|
listHttpRemoteSessions,
|
|
492
608
|
discoverHttpRemoteSessions,
|
|
609
|
+
// Broker peer transport (opt-in relay discovery)
|
|
610
|
+
connectBroker,
|
|
611
|
+
listBrokerPeers,
|
|
612
|
+
listBrokerRemoteSessions,
|
|
613
|
+
discoverBrokerRemoteSessions,
|
|
614
|
+
loadBrokerConfig,
|
|
493
615
|
// File-backed SSH peer enumeration (cross-process — #411)
|
|
494
616
|
listSshPeers,
|
|
495
617
|
getSshPeerHandle,
|
|
496
618
|
getPeerTransport,
|
|
497
|
-
PEERS_PATH
|
|
619
|
+
PEERS_PATH,
|
|
620
|
+
BROKER_CONFIG_PATH
|
|
498
621
|
};
|
package/daemon-control.js
CHANGED
|
@@ -102,6 +102,14 @@ function isLikelyTeleptyDaemon(commandLine) {
|
|
|
102
102
|
return false;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
// telepty#44: the running daemon sets process.title = 'telepty-daemon' (daemon.js:188).
|
|
106
|
+
// On macOS/Linux that REPLACES the command field `ps -axo command=` returns, so the
|
|
107
|
+
// daemon's own title (hyphen) — not its launch command line — is what the process scan
|
|
108
|
+
// and port-owner confirmation see. Recognize it so the stop path is no longer blind to it.
|
|
109
|
+
if (text.includes('telepty-daemon')) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
105
113
|
if (text.includes('telepty daemon')) {
|
|
106
114
|
return true;
|
|
107
115
|
}
|
|
@@ -336,6 +344,7 @@ module.exports = {
|
|
|
336
344
|
cleanupDaemonProcesses,
|
|
337
345
|
clearDaemonState,
|
|
338
346
|
findPortOwnerPid,
|
|
347
|
+
isLikelyTeleptyDaemon,
|
|
339
348
|
isProcessRunning,
|
|
340
349
|
listDaemonProcesses,
|
|
341
350
|
pidMatchesTeleptyCmdline,
|