Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/api-client/src/posthog-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ interface CloudRunOptions {
runSource?: CloudRunSource;
signalReportId?: string;
initialPermissionMode?: PermissionMode;
homeQuickAction?: string;
}

interface CreateTaskRunOptions extends CloudRunOptions {
Expand Down Expand Up @@ -308,6 +309,9 @@ function buildCloudRunRequestBody(
if (options?.initialPermissionMode) {
body.initial_permission_mode = options.initialPermissionMode;
}
if (options?.homeQuickAction) {
body.home_quick_action = options.homeQuickAction;
}

return body;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/home/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export const homeWorkstreamTask = z
status: taskRunStatus.nullable(),
isGenerating: z.boolean(),
needsPermission: z.boolean(),
// Label of the Home quick action that started this run, when it came from one.
// Optional for tolerance of snapshots produced before this field shipped.
quickAction: z.string().nullable().optional(),
})
.strict();
export type HomeWorkstreamTask = z.infer<typeof homeWorkstreamTask>;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/task-detail/taskCreationApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface CreateTaskRunClientOptions {
runSource?: CloudRunSource;
signalReportId?: string;
initialPermissionMode?: string;
homeQuickAction?: string;
}

export interface StartTaskRunClientOptions {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/task-detail/taskCreationSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export class TaskCreationSaga extends Saga<
prAuthorshipMode,
runSource: input.cloudRunSource ?? "manual",
signalReportId: input.signalReportId,
homeQuickAction: input.homeQuickActionLabel,
initialPermissionMode: input.adapter
? (input.executionMode ??
(input.adapter === "codex" ? "auto" : "plan"))
Expand Down
3 changes: 3 additions & 0 deletions packages/shared/src/task-creation-domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export interface TaskCreationInput {
cloudRunSource?: CloudRunSource;
signalReportId?: string;
additionalDirectories?: string[];
// Label of the Home-tab quick action that started this run (e.g. "Fix CI"), so the
// workstream can show which quick actions have been run against it.
homeQuickActionLabel?: string;
}

export interface TaskCreationOutput {
Expand Down
10 changes: 9 additions & 1 deletion packages/ui/src/features/home/components/HomeWorkstreamCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
CircleNotch,
GitBranch,
GitPullRequest,
Sparkle,
Expand Down Expand Up @@ -41,6 +42,7 @@ export function HomeWorkstreamCard({ workstream }: HomeWorkstreamCardProps) {
showTaskInMenu,
hasMenu,
runAction,
isRunningAction,
openTask,
openPr,
} = useWorkstreamPresentation(workstream);
Expand Down Expand Up @@ -159,10 +161,15 @@ export function HomeWorkstreamCard({ workstream }: HomeWorkstreamCardProps) {
<Button
variant="primary"
size="xs"
disabled={isRunningAction}
onClick={() => runAction(primaryBound)}
title={`${primaryBound.situationLabel} → ${primaryBound.skillId}`}
>
<Sparkle size={11} weight="fill" />
{isRunningAction ? (
<CircleNotch size={11} weight="bold" className="animate-spin" />
) : (
<Sparkle size={11} weight="fill" />
)}
{primaryBound.label}
</Button>
) : primaryIsPr ? (
Expand Down Expand Up @@ -193,6 +200,7 @@ export function HomeWorkstreamCard({ workstream }: HomeWorkstreamCardProps) {
onOpenPr={openPr}
onOpenTask={openTask}
size="xs"
runDisabled={isRunningAction}
/>
) : null}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
useBoundActions,
} from "@posthog/ui/features/home/hooks/useBoundActions";
import { useRunWorkstreamAction } from "@posthog/ui/features/home/hooks/useRunWorkstreamAction";
import { useQuickActionStore } from "@posthog/ui/features/home/stores/quickActionStore";
import { useTasks } from "@posthog/ui/features/tasks/useTasks";
import { openTask } from "@posthog/ui/router/useOpenTask";
import { openUrlInBrowser } from "@posthog/ui/utils/browser";
Expand All @@ -41,7 +42,10 @@ interface Props {
export function HomeWorkstreamDetailPanel({ workstream, onClose }: Props) {
const { data: allTasks = [] } = useTasks();
const boundActions = useBoundActions(workstream);
const runAction = useRunWorkstreamAction();
const { run: runAction } = useRunWorkstreamAction();
const isRunningAction = useQuickActionStore(
(s) => !!s.inFlight[workstream.id],
);

const pr = workstream.pr;
const headTask = workstream.tasks[0];
Expand Down Expand Up @@ -124,10 +128,15 @@ export function HomeWorkstreamDetailPanel({ workstream, onClose }: Props) {
<Button
variant="primary"
size="sm"
disabled={isRunningAction}
onClick={() => runAction(primaryAction, workstream)}
title={`${primaryAction.situationLabel} → ${primaryAction.skillId}`}
>
<Sparkle size={12} />
{isRunningAction ? (
<Spinner size={12} className="animate-spin" />
) : (
<Sparkle size={12} />
)}
{primaryAction.label}
</Button>
) : null}
Expand All @@ -143,6 +152,7 @@ export function HomeWorkstreamDetailPanel({ workstream, onClose }: Props) {
{overflowActions.map((action: BoundAction) => (
<DropdownMenu.Item
key={`${action.situationId}::${action.id}`}
disabled={isRunningAction}
onSelect={() => runAction(action, workstream)}
>
<Sparkle size={11} />
Expand Down Expand Up @@ -306,6 +316,15 @@ function TaskRow({
<Text className="min-w-0 flex-1 truncate text-[12px] text-gray-12">
{task.title}
</Text>
{task.quickAction ? (
<span
className="inline-flex shrink-0 items-center gap-1 rounded-full bg-(--accent-a3) px-1.5 py-0.5 text-(--accent-11) text-[10px]"
title={`Started via quick action: ${task.quickAction}`}
>
<Sparkle size={9} weight="fill" />
{task.quickAction}
</span>
) : null}
{task.needsPermission ? (
<Badge variant="warning" title="Awaiting permission">
!
Expand Down
26 changes: 25 additions & 1 deletion packages/ui/src/features/home/components/HomeWorkstreamRow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ChatCircle,
CircleNotch,
GitBranch,
GitPullRequest,
Sparkle,
Expand Down Expand Up @@ -35,6 +36,7 @@ export function HomeWorkstreamRow({ workstream }: HomeWorkstreamRowProps) {
extraSituations,
generating,
needsPermission,
quickActions,
primaryBound,
restBound,
primaryIsPr,
Expand All @@ -43,6 +45,7 @@ export function HomeWorkstreamRow({ workstream }: HomeWorkstreamRowProps) {
showTaskInMenu,
hasMenu,
runAction,
isRunningAction,
openTask,
openPr,
} = useWorkstreamPresentation(workstream);
Expand Down Expand Up @@ -104,6 +107,21 @@ export function HomeWorkstreamRow({ workstream }: HomeWorkstreamRowProps) {
),
});
}
if (quickActions.length > 0) {
meta.push({
key: "quick-actions",
node: (
<span
className="inline-flex items-center gap-1 text-(--accent-11)"
title={`Quick actions run: ${quickActions.join(", ")}`}
>
<Sparkle size={11} weight="fill" />
{quickActions.slice(0, 2).join(", ")}
{quickActions.length > 2 ? ` +${quickActions.length - 2}` : ""}
</span>
),
});
}

return (
<Box
Expand Down Expand Up @@ -159,10 +177,15 @@ export function HomeWorkstreamRow({ workstream }: HomeWorkstreamRowProps) {
<Button
variant="primary"
size="sm"
disabled={isRunningAction}
onClick={() => runAction(primaryBound)}
title={`${primaryBound.situationLabel} → ${primaryBound.skillId}`}
>
<Sparkle size={12} weight="fill" />
{isRunningAction ? (
<CircleNotch size={12} weight="bold" className="animate-spin" />
) : (
<Sparkle size={12} weight="fill" />
)}
{primaryBound.label}
</Button>
) : primaryIsPr ? (
Expand All @@ -185,6 +208,7 @@ export function HomeWorkstreamRow({ workstream }: HomeWorkstreamRowProps) {
onOpenPr={openPr}
onOpenTask={openTask}
size="sm"
runDisabled={isRunningAction}
/>
) : null}
</div>
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/features/home/components/WorkstreamBits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export function WorkstreamOverflowMenu({
onOpenPr,
onOpenTask,
size = "sm",
runDisabled = false,
}: {
restBound: BoundAction[];
showPrInMenu: boolean;
Expand All @@ -144,6 +145,8 @@ export function WorkstreamOverflowMenu({
onOpenPr: () => void;
onOpenTask: () => void;
size?: "sm" | "xs";
/** Disables the task-starting actions while one is already in flight. */
runDisabled?: boolean;
}) {
const sparkleSize = size === "xs" ? 11 : 12;
const dotsSize = size === "xs" ? 15 : 16;
Expand All @@ -158,6 +161,7 @@ export function WorkstreamOverflowMenu({
{restBound.map((action) => (
<DropdownMenu.Item
key={`${action.situationId}::${action.id}`}
disabled={runDisabled}
onSelect={() => onRun(action)}
>
<Sparkle size={sparkleSize} />
Expand Down
Loading
Loading