feat: robot button opens orchestrator session, commands in header

- Robot button (🤖) on HomeScreen now navigates directly to the
  orchestrator's session detail when running, or to the Orchestrator
  overview when not running
- Move CLI commands to a new CommandsScreen, accessible via a
  "Commands" header button on the Orchestrator page
- Remove inline CLI commands from OrchestratorScreen body

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
suraj-markup 2026-03-03 04:47:12 +05:30
parent 170d54cd53
commit d733f107c3
4 changed files with 101 additions and 56 deletions

View File

@ -7,6 +7,7 @@ import TerminalScreen from "../screens/TerminalScreen";
import SettingsScreen from "../screens/SettingsScreen";
import SpawnSessionScreen from "../screens/SpawnSessionScreen";
import OrchestratorScreen from "../screens/OrchestratorScreen";
import CommandsScreen from "../screens/CommandsScreen";
export type RootStackParamList = {
Home: undefined;
@ -15,6 +16,7 @@ export type RootStackParamList = {
Settings: undefined;
SpawnSession: undefined;
Orchestrator: undefined;
Commands: undefined;
};
export const navigationRef = createNavigationContainerRef<RootStackParamList>();
@ -77,6 +79,11 @@ export default function RootNavigator() {
component={OrchestratorScreen}
options={{ title: "Orchestrator" }}
/>
<Stack.Screen
name="Commands"
component={CommandsScreen}
options={{ title: "CLI Commands" }}
/>
</Stack.Navigator>
</NavigationContainer>
);

View File

@ -0,0 +1,75 @@
import React from "react";
import { View, Text, StyleSheet, ScrollView } from "react-native";
const CLI_COMMANDS = [
{ cmd: "ao start [project]", desc: "Start orchestrator + dashboard" },
{ cmd: "ao stop [project]", desc: "Stop orchestrator + dashboard" },
{ cmd: "ao spawn <project> [issue]", desc: "Spawn a session for an issue" },
{ cmd: "ao batch-spawn <project> <issues...>", desc: "Spawn multiple sessions" },
{ cmd: "ao session ls [-p <project>]", desc: "List all active sessions" },
{ cmd: "ao session kill <session>", desc: "Kill a session" },
{ cmd: "ao session restore <session>", desc: "Restore a crashed session" },
{ cmd: "ao session cleanup [-p <project>]", desc: "Clean up merged/closed sessions" },
{ cmd: "ao send <session> [message]", desc: "Send message to a session" },
{ cmd: "ao status [-p <project>]", desc: "Show sessions with PR/CI status" },
{ cmd: "ao review-check [project]", desc: "Check PRs and trigger agents" },
{ cmd: "ao dashboard [-p <port>]", desc: "Start the web dashboard" },
{ cmd: "ao open [target]", desc: "Open session(s) in terminal" },
{ cmd: "ao init [project]", desc: "Initialize config file" },
];
export default function CommandsScreen() {
return (
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
<View style={styles.section}>
<Text style={styles.hint}>Quick reference for managing sessions from terminal.</Text>
{CLI_COMMANDS.map((c, i) => (
<View key={i} style={styles.cmdRow}>
<Text style={styles.cmdText}>{c.cmd}</Text>
<Text style={styles.cmdDesc}>{c.desc}</Text>
</View>
))}
</View>
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#0d1117",
},
content: {
padding: 14,
paddingBottom: 32,
},
section: {
backgroundColor: "#161b22",
borderRadius: 10,
padding: 16,
},
hint: {
color: "#8b949e",
fontSize: 13,
lineHeight: 18,
marginBottom: 12,
},
cmdRow: {
backgroundColor: "#0d1117",
borderRadius: 6,
padding: 10,
marginBottom: 6,
borderWidth: 1,
borderColor: "#30363d",
},
cmdText: {
color: "#58a6ff",
fontSize: 12,
fontFamily: "monospace",
marginBottom: 4,
},
cmdDesc: {
color: "#8b949e",
fontSize: 12,
},
});

View File

@ -32,7 +32,7 @@ function sortSessions(sessions: DashboardSession[]): DashboardSession[] {
}
export default function HomeScreen({ navigation }: Props) {
const { sessions, stats, loading, error, refresh } = useSessions();
const { sessions, stats, orchestratorId, loading, error, refresh } = useSessions();
useSessionNotifications(sessions);
React.useLayoutEffect(() => {
@ -47,7 +47,13 @@ export default function HomeScreen({ navigation }: Props) {
<Text style={{ color: "#3fb950", fontSize: 13, fontWeight: "600" }}>Session</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => navigation.navigate("Orchestrator")}
onPress={() => {
if (orchestratorId) {
navigation.navigate("SessionDetail", { sessionId: orchestratorId });
} else {
navigation.navigate("Orchestrator");
}
}}
>
<Text style={{ fontSize: 20 }}>{"\uD83E\uDD16"}</Text>
</TouchableOpacity>
@ -60,7 +66,7 @@ export default function HomeScreen({ navigation }: Props) {
</View>
),
});
}, [navigation]);
}, [navigation, orchestratorId]);
const sorted = sortSessions(sessions);

View File

@ -14,23 +14,6 @@ import { getAttentionLevel, isTerminal, type DashboardSession } from "../types";
type Props = NativeStackScreenProps<RootStackParamList, "Orchestrator">;
const CLI_COMMANDS = [
{ cmd: "ao start [project]", desc: "Start orchestrator + dashboard" },
{ cmd: "ao stop [project]", desc: "Stop orchestrator + dashboard" },
{ cmd: "ao spawn <project> [issue]", desc: "Spawn a session for an issue" },
{ cmd: "ao batch-spawn <project> <issues...>", desc: "Spawn multiple sessions" },
{ cmd: "ao session ls [-p <project>]", desc: "List all active sessions" },
{ cmd: "ao session kill <session>", desc: "Kill a session" },
{ cmd: "ao session restore <session>", desc: "Restore a crashed session" },
{ cmd: "ao session cleanup [-p <project>]", desc: "Clean up merged/closed sessions" },
{ cmd: "ao send <session> [message]", desc: "Send message to a session" },
{ cmd: "ao status [-p <project>]", desc: "Show sessions with PR/CI status" },
{ cmd: "ao review-check [project]", desc: "Check PRs and trigger agents" },
{ cmd: "ao dashboard [-p <port>]", desc: "Start the web dashboard" },
{ cmd: "ao open [target]", desc: "Open session(s) in terminal" },
{ cmd: "ao init [project]", desc: "Initialize config file" },
];
function getZoneCounts(sessions: DashboardSession[]) {
const counts = { merge: 0, respond: 0, review: 0, pending: 0, working: 0, done: 0 };
for (const s of sessions) {
@ -43,6 +26,16 @@ function getZoneCounts(sessions: DashboardSession[]) {
export default function OrchestratorScreen({ navigation }: Props) {
const { sessions, stats, orchestratorId, loading, error, refresh } = useSessions();
React.useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity onPress={() => navigation.navigate("Commands")}>
<Text style={{ color: "#58a6ff", fontSize: 14, fontWeight: "600" }}>Commands</Text>
</TouchableOpacity>
),
});
}, [navigation]);
const zones = getZoneCounts(sessions);
const activeSessions = sessions.filter((s) => !isTerminal(s));
@ -115,17 +108,6 @@ export default function OrchestratorScreen({ navigation }: Props) {
<StatRow label="Needs review" value={String(stats?.needsReview ?? 0)} />
</View>
{/* CLI Reference */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>CLI Commands</Text>
<Text style={styles.hint}>Quick reference for managing sessions from terminal.</Text>
{CLI_COMMANDS.map((c, i) => (
<View key={i} style={styles.cmdRow}>
<Text style={styles.cmdText}>{c.cmd}</Text>
<Text style={styles.cmdDesc}>{c.desc}</Text>
</View>
))}
</View>
</ScrollView>
);
}
@ -178,12 +160,6 @@ const styles = StyleSheet.create({
textTransform: "uppercase",
marginBottom: 12,
},
hint: {
color: "#8b949e",
fontSize: 13,
lineHeight: 18,
marginBottom: 12,
},
// Orchestrator card
orchestratorCard: {
backgroundColor: "#0d1117",
@ -260,25 +236,6 @@ const styles = StyleSheet.create({
fontSize: 13,
fontWeight: "600",
},
// CLI commands
cmdRow: {
backgroundColor: "#0d1117",
borderRadius: 6,
padding: 10,
marginBottom: 6,
borderWidth: 1,
borderColor: "#30363d",
},
cmdText: {
color: "#58a6ff",
fontSize: 12,
fontFamily: "monospace",
marginBottom: 4,
},
cmdDesc: {
color: "#8b949e",
fontSize: 12,
},
// Error
errorText: {
color: "#f85149",