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:
parent
170d54cd53
commit
d733f107c3
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue