codehost 0.18.2 → 0.19.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 +7 -0
- package/package.json +1 -1
- package/src/web/discovery.tsx +43 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [0.19.0](https://github.com/snomiao/codehost/compare/v0.18.2...v0.19.0) (2026-06-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **web:** GitHub-URL header/title for the open workspace; agent chips link into the agent-yes console ([83d62bc](https://github.com/snomiao/codehost/commit/83d62bc2ab3e70722f8a4f0f817541bea7cf69a2))
|
|
7
|
+
|
|
1
8
|
## [0.18.2](https://github.com/snomiao/codehost/compare/v0.18.1...v0.18.2) (2026-06-11)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/web/discovery.tsx
CHANGED
|
@@ -58,6 +58,18 @@ function folderQuery(folder?: string): string {
|
|
|
58
58
|
return folder ? `?folder=${encodeURIComponent(folder)}` : "";
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/** Human label for a connected workspace: its GitHub-style URL when the share
|
|
62
|
+
* path is repo-shaped (/gh/owner/repo -> github.com/owner/repo, /git/<host>/…
|
|
63
|
+
* -> <host>/…), else the deep-link path as-is. */
|
|
64
|
+
function shareLabel(path: string | null): string | null {
|
|
65
|
+
if (!path) return null;
|
|
66
|
+
const gh = path.match(/^\/gh\/(.+)$/);
|
|
67
|
+
if (gh) return `github.com/${gh[1]}`;
|
|
68
|
+
const git = path.match(/^\/git\/(.+)$/);
|
|
69
|
+
if (git) return git[1];
|
|
70
|
+
return path;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
/**
|
|
62
74
|
* Find which of the user's saved rooms hosts a server matching a token-less deep
|
|
63
75
|
* link. Opens a short-lived viewer connection to each candidate room in
|
|
@@ -292,6 +304,13 @@ export function Discovery() {
|
|
|
292
304
|
tryAutoConnect();
|
|
293
305
|
}, [serversByRoom, tokens]);
|
|
294
306
|
|
|
307
|
+
// Mirror the open workspace into the tab title (GitHub-style URL), so tabs
|
|
308
|
+
// read as "github.com/owner/repo/tree/main — codehost", not all "Codehost".
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
const label = connState === "connected" ? shareLabel(sharePathRef.current) : null;
|
|
311
|
+
document.title = label ? `${label} — codehost` : "Codehost";
|
|
312
|
+
}, [connState]);
|
|
313
|
+
|
|
295
314
|
// Keep the connection in sync with the URL as servers come and go: reconnect
|
|
296
315
|
// when the workspace named by the address bar (re)appears in a room — covers a
|
|
297
316
|
// daemon restart or a dropped channel while the tab stays open.
|
|
@@ -691,8 +710,10 @@ export function Discovery() {
|
|
|
691
710
|
// Group workspaces by machine: the stable hostId when the daemon advertises
|
|
692
711
|
// one, else the hostname string (older daemons), else the peer stands alone.
|
|
693
712
|
// Agents are machine-level (advertised by the host's root daemon) — collect
|
|
694
|
-
// them per group, deduped by pid across peers
|
|
695
|
-
|
|
713
|
+
// them per group, deduped by pid across peers, each remembering its room so
|
|
714
|
+
// a click can hand the agent-yes console the right token.
|
|
715
|
+
type RoomedAgent = AgentInfo & { room: string };
|
|
716
|
+
const hostGroups: { key: string; label: string; items: typeof filtered; agents: RoomedAgent[] }[] = [];
|
|
696
717
|
for (const t of filtered) {
|
|
697
718
|
const key = t.server.meta?.hostId ?? t.server.meta?.host ?? t.server.peerId;
|
|
698
719
|
let group = hostGroups.find((g) => g.key === key);
|
|
@@ -702,7 +723,7 @@ export function Discovery() {
|
|
|
702
723
|
}
|
|
703
724
|
group.items.push(t);
|
|
704
725
|
for (const a of t.server.meta?.agents ?? []) {
|
|
705
|
-
if (!group.agents.some((x) => x.pid === a.pid)) group.agents.push(a);
|
|
726
|
+
if (!group.agents.some((x) => x.pid === a.pid)) group.agents.push({ ...a, room: t.room });
|
|
706
727
|
}
|
|
707
728
|
}
|
|
708
729
|
const toggleTag = (t: string) =>
|
|
@@ -765,8 +786,15 @@ export function Discovery() {
|
|
|
765
786
|
<header style={styles.header}>
|
|
766
787
|
<span style={styles.brand}>codehost</span>
|
|
767
788
|
<span style={styles.dim}>·</span>
|
|
768
|
-
<span
|
|
769
|
-
|
|
789
|
+
<span
|
|
790
|
+
style={styles.cwd}
|
|
791
|
+
title={`${activeServer?.meta?.name ?? ""} ${activeServer?.meta?.cwd ?? ""}`.trim()}
|
|
792
|
+
>
|
|
793
|
+
{shareLabel(sharePathRef.current) ??
|
|
794
|
+
activeServer?.meta?.cwd ??
|
|
795
|
+
activeServer?.meta?.name ??
|
|
796
|
+
activePeerId?.slice(0, 8)}
|
|
797
|
+
</span>
|
|
770
798
|
<span style={{ flex: 1 }} />
|
|
771
799
|
<button
|
|
772
800
|
style={styles.shareBtn}
|
|
@@ -959,14 +987,20 @@ export function Discovery() {
|
|
|
959
987
|
{g.agents.length > 0 && (
|
|
960
988
|
<div style={styles.agentRow}>
|
|
961
989
|
{g.agents.map((a) => (
|
|
962
|
-
<
|
|
990
|
+
<a
|
|
963
991
|
key={a.pid}
|
|
964
992
|
style={styles.agentChip}
|
|
965
|
-
title={`${a.cwd}${a.title ? `\n${a.title}` : ""}`}
|
|
993
|
+
title={`${a.cwd}${a.title ? `\n${a.title}` : ""}\nopen in the agent-yes console`}
|
|
994
|
+
// Tail & send live in the agent-yes console — it joins
|
|
995
|
+
// this same room as a viewer (token rides the fragment,
|
|
996
|
+
// never sent to a server) and auto-selects the pid.
|
|
997
|
+
href={`https://agent-yes.com/?pid=${a.pid}#ch:${encodeURIComponent(a.room)}`}
|
|
998
|
+
target="_blank"
|
|
999
|
+
rel="noopener"
|
|
966
1000
|
>
|
|
967
1001
|
<span style={{ color: a.state === "active" ? "#4ec9b0" : "#777" }}>●</span> {a.tool}{" "}
|
|
968
1002
|
{a.pid}
|
|
969
|
-
</
|
|
1003
|
+
</a>
|
|
970
1004
|
))}
|
|
971
1005
|
</div>
|
|
972
1006
|
)}
|
|
@@ -1081,7 +1115,7 @@ const styles: Record<string, React.CSSProperties> = {
|
|
|
1081
1115
|
agentRow: { display: "flex", flexWrap: "wrap", gap: 6, margin: "0 0 8px" },
|
|
1082
1116
|
agentChip: {
|
|
1083
1117
|
fontFamily: "monospace", fontSize: 11.5, padding: "2px 8px", borderRadius: 999,
|
|
1084
|
-
border: "1px solid #3d3d3d", color: "#9aa4af",
|
|
1118
|
+
border: "1px solid #3d3d3d", color: "#9aa4af", textDecoration: "none", cursor: "pointer",
|
|
1085
1119
|
},
|
|
1086
1120
|
card: { display: "flex", alignItems: "center", gap: 12, background: "#252525", border: "1px solid #3d3d3d", borderRadius: 8, padding: "12px 14px" },
|
|
1087
1121
|
cardMain: { flex: 1, minWidth: 0 },
|