@surething/cockpit 1.0.216 → 1.0.218
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/.next-prod/BUILD_ID +1 -1
- package/.next-prod/app-path-routes-manifest.json +2 -2
- package/.next-prod/build-manifest.json +2 -2
- package/.next-prod/prerender-manifest.json +3 -3
- package/.next-prod/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/_global-error.html +1 -1
- package/.next-prod/server/app/_global-error.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/_not-found.html +1 -1
- package/.next-prod/server/app/_not-found.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next-prod/server/app/api/chat/deepseek/route.js +1 -1
- package/.next-prod/server/app/api/chat/route.js +1 -1
- package/.next-prod/server/app/api/extension/version/route.js.nft.json +1 -1
- package/.next-prod/server/app/api/projectGraph/file-functions/route.js +1 -1
- package/.next-prod/server/app/api/scheduled-tasks/route.js +1 -1
- package/.next-prod/server/app/api/terminal/bubble-order/route.js +1 -1
- package/.next-prod/server/app/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/project/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/review/[id]/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app-paths-manifest.json +2 -2
- package/.next-prod/server/chunks/2939.js +1 -1
- package/.next-prod/server/chunks/8916.js +1 -1
- package/.next-prod/server/chunks/9658.js +7 -7
- package/.next-prod/server/chunks/9877.js +1 -1
- package/.next-prod/server/functions-config-manifest.json +1 -0
- package/.next-prod/server/middleware-build-manifest.js +1 -1
- package/.next-prod/server/pages/404.html +1 -1
- package/.next-prod/server/pages/500.html +1 -1
- package/.next-prod/server/server-reference-manifest.json +1 -1
- package/.next-prod/static/chunks/6345-2637497e8b101740.js +14 -0
- package/.next-prod/static/chunks/6917-ed0e9c62a123d529.js +29 -0
- package/.next-prod/static/chunks/app/{layout-a0362651ba6e6e6f.js → layout-1659a95e6c4a6bb5.js} +1 -1
- package/.next-prod/static/chunks/app/{page-1b14cabf47df9ff7.js → page-afcbd897b4c3600f.js} +1 -1
- package/.next-prod/static/chunks/app/project/{page-1b14cabf47df9ff7.js → page-afcbd897b4c3600f.js} +1 -1
- package/.next-prod/static/css/f4a773117ca8af75.css +1 -0
- package/.next-prod/trace +13 -13
- package/.next-prod/trace-build +1 -1
- package/README.md +8 -7
- package/README.zh.md +8 -7
- package/bin/cock-browser.messages.mjs +176 -0
- package/bin/cock-browser.mjs +290 -18
- package/bin/cock-codegraph.mjs +21 -6
- package/bin/cock-connection.mjs +151 -0
- package/bin/cock.mjs +12 -1
- package/bin/setup-dev.mjs +15 -13
- package/chrome-extension/automation.js +684 -32
- package/chrome-extension/manifest.json +1 -1
- package/chrome-extension/messages.js +45 -0
- package/dist/{chunk-CZWJPTRO.mjs → chunk-GCYLMG43.mjs} +2486 -1047
- package/dist/chunk-O4P2J44N.mjs +314 -0
- package/dist/{chunk-KRTISG5I.mjs → chunk-WOM47O75.mjs} +245 -10
- package/dist/httpApi.mjs +140 -7
- package/dist/scheduledTasks.mjs +15 -1159
- package/dist/{server-OSOMFNXR.mjs → server-SNB4H35J.mjs} +8 -2
- package/dist/wsServer.mjs +27 -19
- package/package.json +3 -5
- package/server.mjs +5 -1
- package/.next-prod/static/chunks/5188-415582403ef0e29c.js +0 -29
- package/.next-prod/static/chunks/6345-e5ceeb2aeb698eb6.js +0 -14
- package/.next-prod/static/css/cc6d733cdf607b30.css +0 -1
- package/dist/chunk-ZJ6CC3MH.mjs +0 -223
- /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → bOkuiIr_nWzG5GjPLNqdN}/_buildManifest.js +0 -0
- /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → bOkuiIr_nWzG5GjPLNqdN}/_ssgManifest.js +0 -0
package/dist/httpApi.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
addOutputListener,
|
|
4
4
|
createPendingRequest,
|
|
5
5
|
getBrowserByShortId,
|
|
6
|
+
getBrowserHealth,
|
|
6
7
|
getFirstAvailableLine,
|
|
7
8
|
getRunningCommand,
|
|
8
9
|
getTerminalByShortId,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
listBrowsers,
|
|
11
12
|
listTerminals,
|
|
12
13
|
readAround,
|
|
14
|
+
readBubbleTitles,
|
|
13
15
|
readHead,
|
|
14
16
|
readSince,
|
|
15
17
|
readTail,
|
|
@@ -19,10 +21,10 @@ import {
|
|
|
19
21
|
unregisterBrowser,
|
|
20
22
|
unregisterTerminal,
|
|
21
23
|
writeStdinToCommand
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-WOM47O75.mjs";
|
|
23
25
|
import {
|
|
24
26
|
getTerminalHistoryPath
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-GCYLMG43.mjs";
|
|
26
28
|
import "./chunk-7P6ASYW6.mjs";
|
|
27
29
|
|
|
28
30
|
// src/lib/httpApi.ts
|
|
@@ -30,6 +32,7 @@ import { parse } from "url";
|
|
|
30
32
|
import { readFile } from "fs/promises";
|
|
31
33
|
import { randomUUID } from "crypto";
|
|
32
34
|
import { WebSocket } from "ws";
|
|
35
|
+
import { resolve as resolvePath } from "path";
|
|
33
36
|
async function readFinishedOutput(projectCwd, tabId, commandId) {
|
|
34
37
|
try {
|
|
35
38
|
const historyPath = getTerminalHistoryPath(projectCwd, tabId);
|
|
@@ -389,37 +392,167 @@ async function handleBrowserApi(req, res) {
|
|
|
389
392
|
sendJson(200, { ok: true });
|
|
390
393
|
return true;
|
|
391
394
|
}
|
|
395
|
+
if (action === "health" && !cmdParams?.deep) {
|
|
396
|
+
if (!id) {
|
|
397
|
+
sendJson(400, { ok: false, error: "Missing browser id" });
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
sendJson(200, { ok: true, data: getBrowserHealth(id) });
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
392
403
|
if (!id) {
|
|
393
404
|
sendJson(400, { ok: false, error: "Missing browser id" });
|
|
394
405
|
return true;
|
|
395
406
|
}
|
|
396
407
|
const browser = getBrowserByShortId(id);
|
|
397
408
|
if (!browser) {
|
|
398
|
-
|
|
409
|
+
const all = listBrowsers().map((b) => b.shortId);
|
|
410
|
+
const suggestions = fuzzyTopK(id, all, 3);
|
|
411
|
+
const hint = suggestions.length ? `
|
|
412
|
+
Did you mean: ${suggestions.join(", ")}?` : all.length ? `
|
|
413
|
+
Available: ${all.join(", ")}` : "\n No browsers currently connected. Open a browser bubble in the cockpit console.";
|
|
414
|
+
sendJson(404, {
|
|
415
|
+
ok: false,
|
|
416
|
+
error: `Browser "${id}" not found.${hint}
|
|
417
|
+
Run: cockpit browser list`
|
|
418
|
+
});
|
|
399
419
|
return true;
|
|
400
420
|
}
|
|
401
421
|
if (!browser.ws || browser.ws.readyState !== WebSocket.OPEN) {
|
|
402
422
|
sendJson(503, {
|
|
403
423
|
ok: false,
|
|
404
|
-
error: `Browser "${id}" is disconnected
|
|
424
|
+
error: `Browser "${id}" is disconnected (WS closed).
|
|
425
|
+
Recover:
|
|
426
|
+
1. Refresh the browser tab to re-register the extension.
|
|
427
|
+
2. Run \`cockpit browser list\` to confirm the shortId.
|
|
428
|
+
3. If the bubble is gone, re-open it from the cockpit console panel.`
|
|
405
429
|
});
|
|
406
430
|
return true;
|
|
407
431
|
}
|
|
432
|
+
const wsAction = action === "health" ? "health_deep" : action;
|
|
408
433
|
const reqId = `r-${randomUUID().slice(0, 8)}`;
|
|
409
|
-
const sent = sendCommandToBrowser(id, reqId,
|
|
434
|
+
const sent = sendCommandToBrowser(id, reqId, wsAction, cmdParams);
|
|
410
435
|
if (!sent) {
|
|
411
|
-
sendJson(503, { ok: false, error: "Failed to send command" });
|
|
436
|
+
sendJson(503, { ok: false, error: "Failed to send command (WS write failed)" });
|
|
412
437
|
return true;
|
|
413
438
|
}
|
|
414
439
|
try {
|
|
415
440
|
const data = await createPendingRequest(reqId, timeout);
|
|
416
441
|
sendJson(200, { ok: true, data });
|
|
417
442
|
} catch (err) {
|
|
418
|
-
|
|
443
|
+
const msg = err.message;
|
|
444
|
+
if (/timeout/i.test(msg)) {
|
|
445
|
+
const h = getBrowserHealth(id);
|
|
446
|
+
sendJson(504, {
|
|
447
|
+
ok: false,
|
|
448
|
+
error: `${msg} (action "${action}").
|
|
449
|
+
Bridge state: ws=${h.ws} pending=${h.pendingCommands}` + (h.lastSuccessMs !== null ? ` lastSuccess=${Math.round(h.lastSuccessMs / 1e3)}s ago (${h.lastSuccessAction})` : "") + `
|
|
450
|
+
Diagnose:
|
|
451
|
+
cockpit browser ${id} health # cheap server-side probe
|
|
452
|
+
cockpit browser ${id} wait --extension-ready (Phase 2)
|
|
453
|
+
If the bridge state shows fresh activity, the page itself is blocked.
|
|
454
|
+
Consider a service-level test if driven by an async LLM/agent flow.`
|
|
455
|
+
});
|
|
456
|
+
} else {
|
|
457
|
+
sendJson(504, { ok: false, error: msg });
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
function fuzzyTopK(input, candidates, k) {
|
|
463
|
+
if (!input || !candidates.length) return [];
|
|
464
|
+
const inputLow = input.toLowerCase();
|
|
465
|
+
const bag = bagCounts(inputLow);
|
|
466
|
+
const scored = candidates.map((c) => {
|
|
467
|
+
const cl = c.toLowerCase();
|
|
468
|
+
const cBag = bagCounts(cl);
|
|
469
|
+
let inter = 0;
|
|
470
|
+
for (const [ch, n] of bag) inter += Math.min(n, cBag.get(ch) ?? 0);
|
|
471
|
+
const ratio = inter / Math.max(inputLow.length, cl.length);
|
|
472
|
+
const startsWith = cl.startsWith(inputLow) ? 0.5 : 0;
|
|
473
|
+
const contains = cl.includes(inputLow) ? 0.3 : 0;
|
|
474
|
+
return { c, score: ratio + startsWith + contains };
|
|
475
|
+
});
|
|
476
|
+
scored.sort((a, b) => b.score - a.score);
|
|
477
|
+
return scored.slice(0, k).filter((s) => s.score >= 0.6).map((s) => s.c);
|
|
478
|
+
}
|
|
479
|
+
function bagCounts(s) {
|
|
480
|
+
const m = /* @__PURE__ */ new Map();
|
|
481
|
+
for (const ch of s) m.set(ch, (m.get(ch) ?? 0) + 1);
|
|
482
|
+
return m;
|
|
483
|
+
}
|
|
484
|
+
async function handleConnectionApi(req, res) {
|
|
485
|
+
const { pathname } = parse(req.url || "", true);
|
|
486
|
+
const match = pathname?.match(/^\/api\/connection\/([a-z]+)$/);
|
|
487
|
+
if (!match || req.method !== "POST") return false;
|
|
488
|
+
if (match[1] !== "list") return false;
|
|
489
|
+
const chunks = [];
|
|
490
|
+
for await (const chunk of req) chunks.push(chunk);
|
|
491
|
+
let body = {};
|
|
492
|
+
try {
|
|
493
|
+
body = JSON.parse(Buffer.concat(chunks).toString());
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
const sendJson = (status, data) => {
|
|
497
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
498
|
+
res.end(JSON.stringify(data));
|
|
499
|
+
};
|
|
500
|
+
const filterCwd = body.cwd ? resolvePath(body.cwd) : void 0;
|
|
501
|
+
const aliveOnly = !body.all;
|
|
502
|
+
const terms = listTerminals(getRunningCommand);
|
|
503
|
+
const browsers = listBrowsers();
|
|
504
|
+
const sameCwd = (entryCwd) => !filterCwd ? true : !!entryCwd && resolvePath(entryCwd) === filterCwd;
|
|
505
|
+
const SEP = String.fromCharCode(31);
|
|
506
|
+
const cwdTabPairs = /* @__PURE__ */ new Set();
|
|
507
|
+
for (const t of terms) {
|
|
508
|
+
if (t.projectCwd && t.tabId) cwdTabPairs.add(`${t.projectCwd}${SEP}${t.tabId}`);
|
|
509
|
+
}
|
|
510
|
+
for (const b of browsers) {
|
|
511
|
+
if (b.projectCwd && b.tabId) cwdTabPairs.add(`${b.projectCwd}${SEP}${b.tabId}`);
|
|
512
|
+
}
|
|
513
|
+
const titlesByPair = /* @__PURE__ */ new Map();
|
|
514
|
+
await Promise.all(
|
|
515
|
+
Array.from(cwdTabPairs).map(async (pair) => {
|
|
516
|
+
const [cwd, tabId] = pair.split(SEP);
|
|
517
|
+
titlesByPair.set(pair, await readBubbleTitles(cwd, tabId));
|
|
518
|
+
})
|
|
519
|
+
);
|
|
520
|
+
const titleOf = (cwd, tabId, key) => {
|
|
521
|
+
if (!cwd || !tabId) return void 0;
|
|
522
|
+
const t = titlesByPair.get(`${cwd}${SEP}${tabId}`)?.[key];
|
|
523
|
+
return t || void 0;
|
|
524
|
+
};
|
|
525
|
+
const out = [];
|
|
526
|
+
for (const t of terms) {
|
|
527
|
+
if (!sameCwd(t.projectCwd)) continue;
|
|
528
|
+
if (aliveOnly && !t.running) continue;
|
|
529
|
+
out.push({
|
|
530
|
+
type: "terminal",
|
|
531
|
+
shortId: t.shortId,
|
|
532
|
+
title: titleOf(t.projectCwd, t.tabId, t.commandId),
|
|
533
|
+
projectCwd: t.projectCwd,
|
|
534
|
+
tabId: t.tabId,
|
|
535
|
+
command: t.command,
|
|
536
|
+
alive: t.running
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
for (const b of browsers) {
|
|
540
|
+
if (!sameCwd(b.projectCwd)) continue;
|
|
541
|
+
if (aliveOnly && !b.connected) continue;
|
|
542
|
+
out.push({
|
|
543
|
+
type: "browser",
|
|
544
|
+
shortId: b.shortId,
|
|
545
|
+
title: titleOf(b.projectCwd, b.tabId, b.fullId),
|
|
546
|
+
projectCwd: b.projectCwd,
|
|
547
|
+
tabId: b.tabId,
|
|
548
|
+
alive: b.connected
|
|
549
|
+
});
|
|
419
550
|
}
|
|
551
|
+
sendJson(200, { ok: true, data: out });
|
|
420
552
|
return true;
|
|
421
553
|
}
|
|
422
554
|
export {
|
|
423
555
|
handleBrowserApi,
|
|
556
|
+
handleConnectionApi,
|
|
424
557
|
handleTerminalApi
|
|
425
558
|
};
|