Skip to content

Commit 904b93e

Browse files
committed
feat: add Open In Browser keybind to agents, axons, and benchmarks
1 parent 7565d45 commit 904b93e

11 files changed

Lines changed: 83 additions & 0 deletions

src/commands/agent/list.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import { useExitOnCtrlC } from "../../hooks/useExitOnCtrlC.js";
3131
import { useCursorPagination } from "../../hooks/useCursorPagination.js";
3232
import { useListSearch } from "../../hooks/useListSearch.js";
3333
import { useNavigation } from "../../store/navigationStore.js";
34+
import { openInBrowser } from "../../utils/browser.js";
35+
import { getAgentUrl } from "../../utils/url.js";
3436

3537
interface ListOptions {
3638
full?: boolean;
@@ -532,6 +534,8 @@ export const ListAgentsUI = ({
532534
setSelectedOperation(0);
533535
} else if (input === "c" && activeTab === "private") {
534536
navigate("agent-create");
537+
} else if (input === "o" && selectedAgentItem) {
538+
openInBrowser(getAgentUrl(selectedAgentItem.id));
535539
} else if (input === "/") {
536540
search.enterSearchMode();
537541
} else if (key.escape) {
@@ -771,6 +775,7 @@ export const ListAgentsUI = ({
771775
{ key: "Tab", label: "Switch tab" },
772776
{ key: "Enter", label: "Details" },
773777
{ key: "a", label: "Actions" },
778+
{ key: "o", label: "Browser" },
774779
{ key: "c", label: "Create", condition: activeTab === "private" },
775780
{ key: "/", label: "Search" },
776781
{ key: "Esc", label: "Back" },

src/commands/axon/list.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { useExitOnCtrlC } from "../../hooks/useExitOnCtrlC.js";
2222
import { useCursorPagination } from "../../hooks/useCursorPagination.js";
2323
import { useListSearch } from "../../hooks/useListSearch.js";
2424
import { useNavigation } from "../../store/navigationStore.js";
25+
import { openInBrowser } from "../../utils/browser.js";
26+
import { getAxonUrl } from "../../utils/url.js";
2527

2628
// ─── CLI ─────────────────────────────────────────────────────────────────────
2729

@@ -284,6 +286,8 @@ export const ListAxonsUI = ({
284286
} else if (input === "a" && selectedAxonItem) {
285287
setShowPopup(true);
286288
setSelectedOperation(0);
289+
} else if (input === "o" && selectedAxonItem) {
290+
openInBrowser(getAxonUrl(selectedAxonItem.id));
287291
} else if (input === "/") {
288292
search.enterSearchMode();
289293
} else if (key.escape) {
@@ -430,6 +434,7 @@ export const ListAxonsUI = ({
430434
},
431435
{ key: "Enter", label: "Details" },
432436
{ key: "a", label: "Actions" },
437+
{ key: "o", label: "Browser" },
433438
{ key: "/", label: "Search" },
434439
{ key: "Esc", label: "Back" },
435440
]}

src/screens/AgentDetailScreen.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { ErrorMessage } from "../components/ErrorMessage.js";
2222
import { Breadcrumb } from "../components/Breadcrumb.js";
2323
import { ConfirmationPrompt } from "../components/ConfirmationPrompt.js";
2424
import { colors } from "../utils/theme.js";
25+
import { getAgentUrl } from "../utils/url.js";
2526

2627
interface AgentDetailScreenProps {
2728
agentId?: string;
@@ -332,6 +333,7 @@ export function AgentDetailScreen({ agentId }: AgentDetailScreenProps) {
332333
resourceType="Agents"
333334
getDisplayName={(a) => a.name}
334335
getId={(a) => a.id}
336+
getUrl={(a) => getAgentUrl(a.id)}
335337
getStatus={() => (agent.is_public ? "public" : "private")}
336338
detailSections={detailSections}
337339
operations={operations}

src/screens/AxonDetailScreen.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { SpinnerComponent } from "../components/Spinner.js";
1616
import { ErrorMessage } from "../components/ErrorMessage.js";
1717
import { Breadcrumb } from "../components/Breadcrumb.js";
1818
import { colors } from "../utils/theme.js";
19+
import { getAxonUrl } from "../utils/url.js";
1920

2021
interface AxonDetailScreenProps {
2122
axonId?: string;
@@ -143,6 +144,7 @@ export function AxonDetailScreen({ axonId }: AxonDetailScreenProps) {
143144
resourceType="Axons"
144145
getDisplayName={(a) => a.name ?? a.id}
145146
getId={(a) => a.id}
147+
getUrl={(a) => getAxonUrl(a.id)}
146148
getStatus={() => "active"}
147149
detailSections={detailSections}
148150
operations={[]}

src/screens/BenchmarkDetailScreen.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { SpinnerComponent } from "../components/Spinner.js";
1818
import { ErrorMessage } from "../components/ErrorMessage.js";
1919
import { Breadcrumb } from "../components/Breadcrumb.js";
2020
import { colors } from "../utils/theme.js";
21+
import { getBenchmarkUrl } from "../utils/url.js";
2122

2223
interface BenchmarkDetailScreenProps {
2324
benchmarkId?: string;
@@ -275,6 +276,7 @@ export function BenchmarkDetailScreen({
275276
resourceType="Benchmark Definitions"
276277
getDisplayName={(b) => b.name || b.id}
277278
getId={(b) => b.id}
279+
getUrl={(b) => getBenchmarkUrl(b.id, !!b.is_public)}
278280
getStatus={(b) => (b as any).status}
279281
detailSections={detailSections}
280282
operations={operations}

src/screens/BenchmarkListScreen.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929
listPublicBenchmarks,
3030
} from "../services/benchmarkService.js";
3131
import type { Benchmark } from "../store/benchmarkStore.js";
32+
import { openInBrowser } from "../utils/browser.js";
33+
import { getBenchmarkUrl } from "../utils/url.js";
3234

3335
export function BenchmarkListScreen() {
3436
const { exit: inkExit } = useApp();
@@ -281,6 +283,8 @@ export function BenchmarkListScreen() {
281283
} else if (input === "a" && selectedBenchmark) {
282284
setShowPopup(true);
283285
setSelectedOperation(0);
286+
} else if (input === "o" && selectedBenchmark) {
287+
openInBrowser(getBenchmarkUrl(selectedBenchmark.id, showPublic));
284288
} else if (input === "s" && selectedBenchmark) {
285289
// Quick shortcut to create a job
286290
navigate("benchmark-job-create", {
@@ -463,6 +467,7 @@ export function BenchmarkListScreen() {
463467
{ key: "Enter", label: "Details" },
464468
{ key: "s", label: "Create Job" },
465469
{ key: "a", label: "Actions" },
470+
{ key: "o", label: "Browser" },
466471
{ key: "Tab", label: "Switch tab" },
467472
{ key: "/", label: "Search" },
468473
{ key: "Esc", label: "Back" },

src/screens/BenchmarkRunDetailScreen.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
createComponentColumn,
3333
} from "../components/Table.js";
3434
import { colors } from "../utils/theme.js";
35+
import { getBenchmarkRunUrl } from "../utils/url.js";
3536

3637
interface BenchmarkRunDetailScreenProps {
3738
benchmarkRunId?: string;
@@ -621,6 +622,7 @@ export function BenchmarkRunDetailScreen({
621622
resourceType="Benchmark Runs"
622623
getDisplayName={(r) => r.name || r.id}
623624
getId={(r) => r.id}
625+
getUrl={(r) => getBenchmarkRunUrl(r.id, r.benchmark_id)}
624626
getStatus={(r) => r.state}
625627
detailSections={detailSections}
626628
operations={operations}

src/screens/BenchmarkRunListScreen.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { useCursorPagination } from "../hooks/useCursorPagination.js";
2626
import { useListSearch } from "../hooks/useListSearch.js";
2727
import { listBenchmarkRuns } from "../services/benchmarkService.js";
2828
import type { BenchmarkRun } from "../store/benchmarkStore.js";
29+
import { openInBrowser } from "../utils/browser.js";
30+
import { getBenchmarkRunUrl } from "../utils/url.js";
2931

3032
export function BenchmarkRunListScreen() {
3133
const { exit: inkExit } = useApp();
@@ -272,6 +274,10 @@ export function BenchmarkRunListScreen() {
272274
} else if (input === "a" && selectedRun) {
273275
setShowPopup(true);
274276
setSelectedOperation(0);
277+
} else if (input === "o" && selectedRun) {
278+
openInBrowser(
279+
getBenchmarkRunUrl(selectedRun.id, selectedRun.benchmark_id),
280+
);
275281
} else if (input === "j") {
276282
// Quick shortcut to create a new job
277283
navigate("benchmark-job-create");
@@ -433,6 +439,7 @@ export function BenchmarkRunListScreen() {
433439
{ key: "Enter", label: "Details" },
434440
{ key: "j", label: "New Job" },
435441
{ key: "a", label: "Actions" },
442+
{ key: "o", label: "Browser" },
436443
{ key: "/", label: "Search" },
437444
{ key: "Esc", label: "Back" },
438445
]}

src/screens/ScenarioRunDetailScreen.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { SpinnerComponent } from "../components/Spinner.js";
2222
import { ErrorMessage } from "../components/ErrorMessage.js";
2323
import { Breadcrumb, type BreadcrumbItem } from "../components/Breadcrumb.js";
2424
import { colors } from "../utils/theme.js";
25+
import { getScenarioRunUrl } from "../utils/url.js";
2526

2627
interface ScenarioRunDetailScreenProps {
2728
scenarioRunId?: string;
@@ -340,6 +341,7 @@ export function ScenarioRunDetailScreen({
340341
resourceType="Scenario Runs"
341342
getDisplayName={(r) => r.name || r.id}
342343
getId={(r) => r.id}
344+
getUrl={(r) => getScenarioRunUrl(r.scenario_id, r.id)}
343345
getStatus={(r) => r.state}
344346
detailSections={detailSections}
345347
operations={operations}

src/screens/ScenarioRunListScreen.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { useCursorPagination } from "../hooks/useCursorPagination.js";
2626
import { useListSearch } from "../hooks/useListSearch.js";
2727
import { listScenarioRuns } from "../services/benchmarkService.js";
2828
import type { ScenarioRun } from "../store/benchmarkStore.js";
29+
import { openInBrowser } from "../utils/browser.js";
30+
import { getScenarioRunUrl } from "../utils/url.js";
2931

3032
interface ScenarioRunListScreenProps {
3133
benchmarkRunId?: string;
@@ -269,6 +271,8 @@ export function ScenarioRunListScreen({
269271
} else if (input === "a" && selectedRun) {
270272
setShowPopup(true);
271273
setSelectedOperation(0);
274+
} else if (input === "o" && selectedRun) {
275+
openInBrowser(getScenarioRunUrl(selectedRun.scenario_id, selectedRun.id));
272276
} else if (input === "/") {
273277
search.enterSearchMode();
274278
} else if (key.escape) {
@@ -424,6 +428,7 @@ export function ScenarioRunListScreen({
424428
},
425429
{ key: "Enter", label: "Details" },
426430
{ key: "a", label: "Actions" },
431+
{ key: "o", label: "Browser" },
427432
{ key: "/", label: "Search" },
428433
{ key: "Esc", label: "Back" },
429434
]}

0 commit comments

Comments
 (0)