@dp-pcs/ogp 0.7.2 → 0.8.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 +59 -12
- package/dist/cli/config.d.ts +4 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +45 -2
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/expose.d.ts +4 -1
- package/dist/cli/expose.d.ts.map +1 -1
- package/dist/cli/expose.js +7 -106
- package/dist/cli/expose.js.map +1 -1
- package/dist/cli/install.d.ts +1 -0
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/install.js +8 -2
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/project.d.ts +24 -0
- package/dist/cli/project.d.ts.map +1 -1
- package/dist/cli/project.js +68 -15
- package/dist/cli/project.js.map +1 -1
- package/dist/cli/tunnel.d.ts +65 -0
- package/dist/cli/tunnel.d.ts.map +1 -0
- package/dist/cli/tunnel.js +413 -0
- package/dist/cli/tunnel.js.map +1 -0
- package/dist/cli.js +21 -8
- package/dist/cli.js.map +1 -1
- package/dist/daemon/contribution-signing.d.ts +49 -0
- package/dist/daemon/contribution-signing.d.ts.map +1 -0
- package/dist/daemon/contribution-signing.js +91 -0
- package/dist/daemon/contribution-signing.js.map +1 -0
- package/dist/daemon/message-handler.js +41 -18
- package/dist/daemon/message-handler.js.map +1 -1
- package/dist/daemon/openclaw-bridge.d.ts +6 -0
- package/dist/daemon/openclaw-bridge.d.ts.map +1 -1
- package/dist/daemon/openclaw-bridge.js +27 -12
- package/dist/daemon/openclaw-bridge.js.map +1 -1
- package/dist/daemon/peers.d.ts.map +1 -1
- package/dist/daemon/peers.js +19 -0
- package/dist/daemon/peers.js.map +1 -1
- package/dist/daemon/projects.d.ts +20 -0
- package/dist/daemon/projects.d.ts.map +1 -1
- package/dist/daemon/projects.js +70 -0
- package/dist/daemon/projects.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +43 -2
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/state-lock.d.ts +23 -0
- package/dist/daemon/state-lock.d.ts.map +1 -0
- package/dist/daemon/state-lock.js +115 -0
- package/dist/daemon/state-lock.js.map +1 -0
- package/package.json +13 -3
- package/scripts/completion.bash +25 -6
- package/scripts/completion.zsh +26 -8
- package/skills/ogp-expose/SKILL.md +40 -10
- package/docs/RC1-FEDERATION-TEST-CHECKLIST.md +0 -477
- package/docs/case-studies/CRASH_RESOLUTION_20260407.md +0 -190
- package/docs/case-studies/OpenClaw_Hermes_Status_Report_20260407.md +0 -142
- package/docs/case-studies/OpenClaw_Stability_Fix_Summary.md +0 -209
- package/docs/case-studies/README.md +0 -40
- package/docs/case-studies/crash_observations.md +0 -250
- package/docs/nat-hole-punch-spike.md +0 -399
- package/docs/project-intent-testing.md +0 -97
- package/scripts/render-ogp-overview-video.mjs +0 -454
- package/scripts/test-migration-execute.js +0 -74
- package/scripts/test-migration.js +0 -42
- package/scripts/test-project-intents.mjs +0 -614
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { spawn, execFile, execFileSync } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { loadConfig, requireConfig, getConfigDir } from '../shared/config.js';
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
/**
|
|
10
|
+
* Parse the JSON array emitted by `cloudflared tunnel list --output json`.
|
|
11
|
+
* Filters out deleted tunnels and classifies live = has active connections.
|
|
12
|
+
* Returns [] on any parse failure (caller surfaces the raw error separately).
|
|
13
|
+
*/
|
|
14
|
+
export function parseCloudflaredTunnels(jsonText) {
|
|
15
|
+
let arr;
|
|
16
|
+
try {
|
|
17
|
+
arr = JSON.parse(jsonText);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
if (!Array.isArray(arr))
|
|
23
|
+
return [];
|
|
24
|
+
return arr
|
|
25
|
+
.filter((t) => !t?.deleted_at || String(t.deleted_at).startsWith('0001-01-01'))
|
|
26
|
+
.map((t) => {
|
|
27
|
+
const conns = Array.isArray(t.connections) ? t.connections : [];
|
|
28
|
+
const colos = Array.from(new Set(conns.map((c) => c?.colo_name).filter(Boolean)));
|
|
29
|
+
return {
|
|
30
|
+
tool: 'cloudflared',
|
|
31
|
+
name: typeof t.name === 'string' ? t.name : undefined,
|
|
32
|
+
id: typeof t.id === 'string' ? t.id : undefined,
|
|
33
|
+
live: conns.length > 0,
|
|
34
|
+
detail: colos.length ? `via ${colos.join(', ')}` : undefined,
|
|
35
|
+
source: 'cloudflared tunnel list'
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse the JSON from the ngrok local agent API (http://127.0.0.1:4040/api/tunnels).
|
|
41
|
+
* ngrok historically returns one entry per proto (http + https) for the same
|
|
42
|
+
* forward; we dedupe by public-URL host, preferring https. Returns [] on failure.
|
|
43
|
+
*/
|
|
44
|
+
export function parseNgrokAgentTunnels(jsonText) {
|
|
45
|
+
let obj;
|
|
46
|
+
try {
|
|
47
|
+
obj = JSON.parse(jsonText);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const tunnels = Array.isArray(obj?.tunnels) ? obj.tunnels : [];
|
|
53
|
+
const byHost = new Map();
|
|
54
|
+
for (const t of tunnels) {
|
|
55
|
+
const publicUrl = typeof t?.public_url === 'string' ? t.public_url : undefined;
|
|
56
|
+
if (!publicUrl)
|
|
57
|
+
continue;
|
|
58
|
+
let host;
|
|
59
|
+
try {
|
|
60
|
+
host = new URL(publicUrl).host;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const isHttps = publicUrl.startsWith('https://');
|
|
66
|
+
const existing = byHost.get(host);
|
|
67
|
+
if (existing && !isHttps)
|
|
68
|
+
continue; // keep https over http for same host
|
|
69
|
+
byHost.set(host, {
|
|
70
|
+
tool: 'ngrok',
|
|
71
|
+
name: typeof t.name === 'string' ? t.name : undefined,
|
|
72
|
+
publicUrl,
|
|
73
|
+
target: typeof t?.config?.addr === 'string' ? t.config.addr : undefined,
|
|
74
|
+
live: true,
|
|
75
|
+
detail: typeof t?.proto === 'string' ? t.proto : undefined,
|
|
76
|
+
source: 'ngrok agent (:4040)'
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return Array.from(byHost.values());
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Best-effort extraction of ingress hostnames from a cloudflared config.yml.
|
|
83
|
+
* Used to resolve a public hostname for named tunnels during reconcile.
|
|
84
|
+
*/
|
|
85
|
+
export function parseCloudflaredIngressHosts(yamlText) {
|
|
86
|
+
const hosts = [];
|
|
87
|
+
for (const line of yamlText.split('\n')) {
|
|
88
|
+
const m = line.match(/^\s*-?\s*hostname:\s*["']?([^"'#\s/]+)/);
|
|
89
|
+
if (m)
|
|
90
|
+
hosts.push(m[1]);
|
|
91
|
+
}
|
|
92
|
+
return hosts;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Compare resolvable live public hosts against config gatewayUrl.
|
|
96
|
+
* `liveHosts` is the precomputed set of hosts (ngrok public_url hosts + cloudflared
|
|
97
|
+
* ingress hosts when a cloudflared tunnel is live). Pure; returns null when there is
|
|
98
|
+
* nothing meaningful to report.
|
|
99
|
+
*/
|
|
100
|
+
export function reconcileGatewayUrl(liveHosts, gatewayUrl) {
|
|
101
|
+
if (!gatewayUrl)
|
|
102
|
+
return null;
|
|
103
|
+
let gwHost;
|
|
104
|
+
try {
|
|
105
|
+
gwHost = new URL(gatewayUrl).host;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (liveHosts.length === 0) {
|
|
111
|
+
return {
|
|
112
|
+
verdict: 'none',
|
|
113
|
+
message: `⚠ gatewayUrl ${gwHost} is set but no live tunnel with a resolvable public URL serves it`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (liveHosts.includes(gwHost)) {
|
|
117
|
+
return { verdict: 'match', message: `✓ gatewayUrl ${gwHost} is served by a live tunnel` };
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
verdict: 'mismatch',
|
|
121
|
+
message: `✗ gatewayUrl ${gwHost} does not match any live tunnel (live: ${liveHosts.join(', ')})`
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const PANE_LABEL = {
|
|
125
|
+
cloudflared: 'cloudflared — named tunnels registered to your Cloudflare account',
|
|
126
|
+
ngrok: 'ngrok — tunnels running on this machine'
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Format tunnel panes for the terminal. Pure: takes resolved data, returns a string.
|
|
130
|
+
*/
|
|
131
|
+
export function renderTunnels(panes, reconcile) {
|
|
132
|
+
const lines = [];
|
|
133
|
+
for (const pane of panes) {
|
|
134
|
+
lines.push('');
|
|
135
|
+
lines.push(`▸ ${PANE_LABEL[pane.tool]}`);
|
|
136
|
+
if (pane.error) {
|
|
137
|
+
lines.push(` ⚠ ${pane.error}`);
|
|
138
|
+
if (pane.note)
|
|
139
|
+
lines.push(` ${pane.note}`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (pane.infos.length === 0) {
|
|
143
|
+
lines.push(` (no ${pane.tool} tunnels found)`);
|
|
144
|
+
if (pane.note)
|
|
145
|
+
lines.push(` ${pane.note}`);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const t of pane.infos) {
|
|
149
|
+
const status = t.live ? 'LIVE' : 'idle';
|
|
150
|
+
const label = t.name ?? t.publicUrl ?? t.id ?? '(unnamed)';
|
|
151
|
+
const bits = [
|
|
152
|
+
` [${status}] ${label}`,
|
|
153
|
+
t.publicUrl && t.publicUrl !== label ? `→ ${t.publicUrl}` : '',
|
|
154
|
+
t.target ? `(${t.target})` : '',
|
|
155
|
+
t.id && t.id !== label ? `id=${t.id.slice(0, 8)}` : '',
|
|
156
|
+
t.detail ? t.detail : ''
|
|
157
|
+
].filter(Boolean);
|
|
158
|
+
lines.push(bits.join(' '));
|
|
159
|
+
}
|
|
160
|
+
if (pane.note)
|
|
161
|
+
lines.push(` ${pane.note}`);
|
|
162
|
+
}
|
|
163
|
+
if (reconcile) {
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push(reconcile.message);
|
|
166
|
+
}
|
|
167
|
+
return lines.join('\n');
|
|
168
|
+
}
|
|
169
|
+
/** Check if a command exists in PATH (mirrors framework-detection.ts). */
|
|
170
|
+
function commandExists(command) {
|
|
171
|
+
try {
|
|
172
|
+
const which = process.platform === 'win32' ? 'where' : 'which';
|
|
173
|
+
execFileSync(which, [command], { stdio: 'ignore' });
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
export async function listCloudflaredTunnels() {
|
|
181
|
+
if (!commandExists('cloudflared')) {
|
|
182
|
+
return { tool: 'cloudflared', infos: [], error: 'cloudflared not installed — `brew install cloudflared`' };
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const { stdout } = await execFileAsync('cloudflared', ['tunnel', 'list', '--output', 'json'], {
|
|
186
|
+
timeout: 15000
|
|
187
|
+
});
|
|
188
|
+
return { tool: 'cloudflared', infos: parseCloudflaredTunnels(stdout) };
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
const stderr = (err?.stderr || err?.message || '').toString().trim();
|
|
192
|
+
const note = /login|cert|origincert|not.*authenticat/i.test(stderr)
|
|
193
|
+
? 'Run `cloudflared tunnel login` to authenticate.'
|
|
194
|
+
: undefined;
|
|
195
|
+
return {
|
|
196
|
+
tool: 'cloudflared',
|
|
197
|
+
infos: [],
|
|
198
|
+
error: `cloudflared tunnel list failed: ${stderr.split('\n')[0] || 'unknown error'}`,
|
|
199
|
+
note
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function fetchNgrokAgent() {
|
|
204
|
+
// Probe the default agent port and the next two (multiple agents bump the port).
|
|
205
|
+
for (const port of [4040, 4041, 4042]) {
|
|
206
|
+
try {
|
|
207
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/tunnels`, {
|
|
208
|
+
signal: AbortSignal.timeout(2000)
|
|
209
|
+
});
|
|
210
|
+
if (!res.ok)
|
|
211
|
+
continue;
|
|
212
|
+
const infos = parseNgrokAgentTunnels(await res.text());
|
|
213
|
+
if (infos.length > 0)
|
|
214
|
+
return infos;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// try next port
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
export async function listNgrokTunnels() {
|
|
223
|
+
if (!commandExists('ngrok')) {
|
|
224
|
+
return { tool: 'ngrok', infos: [], error: 'ngrok not installed — `brew install ngrok`' };
|
|
225
|
+
}
|
|
226
|
+
const agent = await fetchNgrokAgent();
|
|
227
|
+
if (agent && agent.length > 0) {
|
|
228
|
+
return { tool: 'ngrok', infos: agent };
|
|
229
|
+
}
|
|
230
|
+
return { tool: 'ngrok', infos: [], note: 'No local ngrok agent running on :4040.' };
|
|
231
|
+
}
|
|
232
|
+
export async function tunnelList(tool) {
|
|
233
|
+
const panes = [];
|
|
234
|
+
if (!tool || tool === 'cloudflared')
|
|
235
|
+
panes.push(await listCloudflaredTunnels());
|
|
236
|
+
if (!tool || tool === 'ngrok')
|
|
237
|
+
panes.push(await listNgrokTunnels());
|
|
238
|
+
// Build the set of resolvable live public hosts for reconcile.
|
|
239
|
+
const liveHosts = [];
|
|
240
|
+
for (const pane of panes) {
|
|
241
|
+
for (const info of pane.infos) {
|
|
242
|
+
if (info.live && info.publicUrl) {
|
|
243
|
+
try {
|
|
244
|
+
liveHosts.push(new URL(info.publicUrl).host);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
/* skip */
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// cloudflared named tunnels: if any is live, treat config.yml ingress hosts as live.
|
|
253
|
+
const cfPane = panes.find((p) => p.tool === 'cloudflared');
|
|
254
|
+
if (cfPane && cfPane.infos.some((i) => i.live)) {
|
|
255
|
+
const cfgPath = path.join(os.homedir(), '.cloudflared', 'config.yml');
|
|
256
|
+
if (fs.existsSync(cfgPath)) {
|
|
257
|
+
liveHosts.push(...parseCloudflaredIngressHosts(fs.readFileSync(cfgPath, 'utf-8')));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const config = loadConfig();
|
|
261
|
+
const reconcile = config ? reconcileGatewayUrl(liveHosts, config.gatewayUrl) : null;
|
|
262
|
+
console.log(renderTunnels(panes, reconcile));
|
|
263
|
+
}
|
|
264
|
+
function getTunnelPidFile() {
|
|
265
|
+
return path.join(getConfigDir(), 'tunnel.pid');
|
|
266
|
+
}
|
|
267
|
+
function getTunnelLogFile() {
|
|
268
|
+
return path.join(getConfigDir(), 'tunnel.log');
|
|
269
|
+
}
|
|
270
|
+
/** True if the ogp-managed tunnel PID file points at a live process. */
|
|
271
|
+
function isManagedTunnelAlive() {
|
|
272
|
+
const pidFile = getTunnelPidFile();
|
|
273
|
+
if (!fs.existsSync(pidFile))
|
|
274
|
+
return false;
|
|
275
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
276
|
+
if (Number.isNaN(pid))
|
|
277
|
+
return false;
|
|
278
|
+
try {
|
|
279
|
+
process.kill(pid, 0);
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function spawnTunnel(tool, port, background) {
|
|
287
|
+
const args = tool === 'cloudflared'
|
|
288
|
+
? ['tunnel', '--url', `http://localhost:${port}`]
|
|
289
|
+
: ['http', port.toString()];
|
|
290
|
+
if (background) {
|
|
291
|
+
const logStream = fs.openSync(getTunnelLogFile(), 'a');
|
|
292
|
+
const proc = spawn(tool, args, { detached: true, stdio: ['ignore', logStream, logStream] });
|
|
293
|
+
proc.unref();
|
|
294
|
+
fs.closeSync(logStream);
|
|
295
|
+
fs.writeFileSync(getTunnelPidFile(), proc.pid.toString(), 'utf-8');
|
|
296
|
+
console.log(`${tool} tunnel started (PID: ${proc.pid})`);
|
|
297
|
+
console.log(`Logs: ${getTunnelLogFile()}`);
|
|
298
|
+
console.log('Run "ogp tunnel stop" to stop the tunnel');
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
const proc = spawn(tool, args, { stdio: 'inherit' });
|
|
302
|
+
proc.on('error', (error) => {
|
|
303
|
+
console.error(`Failed to start ${tool}:`, error);
|
|
304
|
+
console.log(`Make sure ${tool} is installed and in your PATH`);
|
|
305
|
+
});
|
|
306
|
+
proc.on('close', (code) => console.log(`${tool} exited with code ${code}`));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Start a quick tunnel for the given tool. Idempotent: if an ogp-managed tunnel is
|
|
311
|
+
* already alive (or, for ngrok, a local agent is already serving), prints current
|
|
312
|
+
* status instead of starting a duplicate. Note: the duplicate-guard relies on the
|
|
313
|
+
* background PID file (and the ngrok :4040 agent), so a foreground cloudflared quick
|
|
314
|
+
* tunnel started twice cannot be detected — cloudflared exposes no local agent to query.
|
|
315
|
+
*/
|
|
316
|
+
export async function tunnelStart(tool, background = false) {
|
|
317
|
+
const config = requireConfig();
|
|
318
|
+
if (!commandExists(tool)) {
|
|
319
|
+
console.error(`${tool} not installed — \`brew install ${tool}\``);
|
|
320
|
+
process.exitCode = 1;
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (isManagedTunnelAlive()) {
|
|
324
|
+
console.log('An ogp-managed tunnel is already running. Current tunnels:');
|
|
325
|
+
await tunnelList(tool);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (tool === 'ngrok') {
|
|
329
|
+
const agent = await fetchNgrokAgent();
|
|
330
|
+
if (agent && agent.length > 0) {
|
|
331
|
+
console.log('A local ngrok agent is already running. Current tunnels:');
|
|
332
|
+
await tunnelList('ngrok');
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
console.log(`Exposing OGP daemon on port ${config.daemonPort} via ${tool}...`);
|
|
337
|
+
spawnTunnel(tool, config.daemonPort, background);
|
|
338
|
+
}
|
|
339
|
+
/** Stop the ogp-managed tunnel (PID file). Does not affect externally-started tunnels. */
|
|
340
|
+
export function tunnelStop() {
|
|
341
|
+
const pidFile = getTunnelPidFile();
|
|
342
|
+
if (!fs.existsSync(pidFile)) {
|
|
343
|
+
console.log('No ogp-managed tunnel is running.');
|
|
344
|
+
console.log('(Tunnels started outside ogp are not tracked here — stop them with their own CLI.)');
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
349
|
+
if (Number.isNaN(pid)) {
|
|
350
|
+
console.error('Invalid PID in tunnel.pid file');
|
|
351
|
+
fs.unlinkSync(pidFile);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
process.kill(pid, 0);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
console.log('Tunnel is not running (stale PID file)');
|
|
359
|
+
fs.unlinkSync(pidFile);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
process.kill(pid, 'SIGTERM');
|
|
363
|
+
fs.unlinkSync(pidFile);
|
|
364
|
+
console.log('Tunnel stopped');
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
if (error?.code === 'ESRCH') {
|
|
368
|
+
console.log('Tunnel already stopped (process exited between checks)');
|
|
369
|
+
try {
|
|
370
|
+
fs.unlinkSync(pidFile);
|
|
371
|
+
}
|
|
372
|
+
catch { /* already gone */ }
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
console.error('Failed to stop tunnel:', error);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
export const tunnelCommand = new Command('tunnel')
|
|
380
|
+
.description('Inspect and manage cloudflared / ngrok tunnels');
|
|
381
|
+
tunnelCommand
|
|
382
|
+
.command('list')
|
|
383
|
+
.alias('show')
|
|
384
|
+
.description('List running tunnels (cloudflared, ngrok, or both)')
|
|
385
|
+
.argument('[tool]', 'Limit to one tool: cloudflared | ngrok')
|
|
386
|
+
.action(async (tool) => {
|
|
387
|
+
if (tool && tool !== 'cloudflared' && tool !== 'ngrok') {
|
|
388
|
+
console.error(`Unknown tool '${tool}'. Use 'cloudflared' or 'ngrok'.`);
|
|
389
|
+
process.exitCode = 1;
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
await tunnelList(tool);
|
|
393
|
+
});
|
|
394
|
+
tunnelCommand
|
|
395
|
+
.command('start')
|
|
396
|
+
.description('Start a quick tunnel (idempotent — no-op if one is already running)')
|
|
397
|
+
.argument('<tool>', 'cloudflared | ngrok')
|
|
398
|
+
.option('-b, --background', 'Run in background')
|
|
399
|
+
.action(async (tool, options) => {
|
|
400
|
+
if (tool !== 'cloudflared' && tool !== 'ngrok') {
|
|
401
|
+
console.error(`Unknown tool '${tool}'. Use 'cloudflared' or 'ngrok'.`);
|
|
402
|
+
process.exitCode = 1;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
await tunnelStart(tool, options.background ?? false);
|
|
406
|
+
});
|
|
407
|
+
tunnelCommand
|
|
408
|
+
.command('stop')
|
|
409
|
+
.description('Stop the ogp-managed tunnel')
|
|
410
|
+
.action(() => {
|
|
411
|
+
tunnelStop();
|
|
412
|
+
});
|
|
413
|
+
//# sourceMappingURL=tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/cli/tunnel.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ import { requireConfig, loadConfig } from './shared/config.js';
|
|
|
10
10
|
import { loadMetaConfig } from './shared/meta-config.js';
|
|
11
11
|
import { federationList, federationStatus, federationRequest, federationApprove, federationReject, federationRemove, federationSend, federationShowScopes, federationUpdateGrants, federationSendAgentComms, federationConnect, federationInvite, federationAccept, federationSetAlias, federationTagPeer, federationUntagPeer, federationUpdateIdentity } from './cli/federation.js';
|
|
12
12
|
import { expose, stopExpose } from './cli/expose.js';
|
|
13
|
+
import { tunnelCommand } from './cli/tunnel.js';
|
|
13
14
|
import { installLaunchAgent, uninstallLaunchAgent } from './cli/install.js';
|
|
14
15
|
import { installCompletion } from './cli/completion.js';
|
|
15
16
|
import { showPolicies, configurePolicies, addTopic, removeTopic, resetPolicy, showActivity, clearActivity, setDefault, setLogging, setTopic, setPeerDefault } from './cli/agent-comms.js';
|
|
@@ -411,7 +412,14 @@ program
|
|
|
411
412
|
console.log(` Check interval: ${heartbeatConfig.intervalMs / 1000}s`);
|
|
412
413
|
console.log(` Check timeout: ${heartbeatConfig.timeoutMs / 1000}s`);
|
|
413
414
|
console.log(` Max consecutive failures: ${heartbeatConfig.maxConsecutiveFailures}`);
|
|
414
|
-
|
|
415
|
+
// The heartbeat loop runs inside the long-lived daemon process and is started
|
|
416
|
+
// unconditionally at daemon boot (see startHeartbeat()). This `ogp status` command
|
|
417
|
+
// runs in a *separate*, short-lived CLI process where the heartbeat timer is always
|
|
418
|
+
// null, so heartbeatConfig.isRunning here reflects the CLI process, not the daemon —
|
|
419
|
+
// it would always read 'Stopped' even while the daemon's heartbeat is actively
|
|
420
|
+
// checking peers (bd-d1l). The authoritative cross-process signal is whether the
|
|
421
|
+
// daemon itself is running.
|
|
422
|
+
console.log(` Heartbeat status: ${status.running ? 'Running' : 'Stopped'}`);
|
|
415
423
|
});
|
|
416
424
|
/**
|
|
417
425
|
* Pad string to the right with spaces
|
|
@@ -655,17 +663,18 @@ federation
|
|
|
655
663
|
toAgent: options.toAgent
|
|
656
664
|
});
|
|
657
665
|
});
|
|
666
|
+
program.addCommand(tunnelCommand);
|
|
658
667
|
program
|
|
659
|
-
.command('expose')
|
|
660
|
-
.description('
|
|
668
|
+
.command('expose', { hidden: true })
|
|
669
|
+
.description('[deprecated] Use "ogp tunnel start"')
|
|
661
670
|
.option('-m, --method <method>', 'Tunnel method (cloudflared|ngrok)', 'cloudflared')
|
|
662
671
|
.option('-b, --background', 'Run in background')
|
|
663
672
|
.action(async (options) => {
|
|
664
673
|
await expose(options.method, options.background);
|
|
665
674
|
});
|
|
666
675
|
program
|
|
667
|
-
.command('expose-stop')
|
|
668
|
-
.description('
|
|
676
|
+
.command('expose-stop', { hidden: true })
|
|
677
|
+
.description('[deprecated] Use "ogp tunnel stop"')
|
|
669
678
|
.action(() => {
|
|
670
679
|
stopExpose();
|
|
671
680
|
});
|
|
@@ -896,11 +905,13 @@ project
|
|
|
896
905
|
.option('--author <id>', 'Filter by author')
|
|
897
906
|
.option('--search <text>', 'Search by text content')
|
|
898
907
|
.option('--limit <n>', 'Maximum results to return', '20')
|
|
908
|
+
.option('--json', 'Output machine-readable JSON (includes contribution ids + ISO timestamps)')
|
|
899
909
|
.action(async (projectId, options) => {
|
|
900
910
|
const queryOptions = {
|
|
901
911
|
...options,
|
|
902
912
|
entryType: options.type || options.topic, // --type takes precedence; --topic remains a legacy alias
|
|
903
|
-
limit: parseInt(options.limit, 10)
|
|
913
|
+
limit: parseInt(options.limit, 10),
|
|
914
|
+
json: options.json ?? false
|
|
904
915
|
};
|
|
905
916
|
await projectQuery(projectId, queryOptions);
|
|
906
917
|
});
|
|
@@ -943,13 +954,15 @@ project
|
|
|
943
954
|
.option('--topic <name>', 'Filter by entry type (alias for --type)')
|
|
944
955
|
.option('--author <id>', 'Filter by author')
|
|
945
956
|
.option('--limit <n>', 'Maximum results to return', '20')
|
|
946
|
-
.option('--timeout <ms>', 'Response timeout in milliseconds', '
|
|
957
|
+
.option('--timeout <ms>', 'Response timeout in milliseconds', '30000')
|
|
958
|
+
.option('--json', 'Output machine-readable JSON (includes contribution ids + ISO timestamps)')
|
|
947
959
|
.action(async (peerId, projectId, options) => {
|
|
948
960
|
const queryOptions = {
|
|
949
961
|
...options,
|
|
950
962
|
entryType: options.type || options.topic, // --type takes precedence; --topic remains a legacy alias
|
|
951
963
|
limit: parseInt(options.limit, 10),
|
|
952
|
-
timeout: parseInt(options.timeout, 10)
|
|
964
|
+
timeout: parseInt(options.timeout, 10),
|
|
965
|
+
json: options.json ?? false
|
|
953
966
|
};
|
|
954
967
|
await projectQueryPeer(peerId, projectId, queryOptions);
|
|
955
968
|
});
|