Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
484a6c7
refactor(shared): extract task contracts and model policy
richardsolomou Jul 24, 2026
ec5fb80
fix(models): preserve GLM effort policy
richardsolomou Jul 24, 2026
fa2dda4
test(ui): wait for async content
richardsolomou Jul 24, 2026
0960bc3
test(ui): isolate plan approval presentation
richardsolomou Jul 24, 2026
3f608f2
fix(shared): Preserve canonical task artifacts
richardsolomou Jul 28, 2026
9c4235c
test(agent): match canonical model picker order
richardsolomou Jul 28, 2026
b4e9084
Merge main into shared cloud task foundations
richardsolomou Jul 29, 2026
b69d17d
refactor(api-client): extract cloud task transport
richardsolomou Jul 24, 2026
01aec6d
refactor(core): extract cloud task policies
richardsolomou Jul 24, 2026
53e5383
refactor(core): rename cloud task service as engine
richardsolomou Jul 24, 2026
2245a2e
refactor(core): extract portable cloud task engine
richardsolomou Jul 24, 2026
36f9b39
refactor(core): extract repository integration semantics
richardsolomou Jul 24, 2026
3003336
refactor(core): extract pending prompt recovery
richardsolomou Jul 24, 2026
b5204c8
refactor(core): extract plan approval presentation
richardsolomou Jul 24, 2026
7ccd259
refactor(core): extract permission option presentation
richardsolomou Jul 24, 2026
046422e
refactor(core): extract composer controls
richardsolomou Jul 24, 2026
37f1c0b
refactor(core): extract composer model policy
richardsolomou Jul 24, 2026
0a1c884
fix(core): prefer streamed plan content
richardsolomou Jul 24, 2026
e27b337
refactor(core): extract session presentation semantics
richardsolomou Jul 24, 2026
04a7f52
refactor(api-client): expose shared automation contracts
richardsolomou Jul 24, 2026
0b25fcd
refactor(core): extract inbox presentation semantics
richardsolomou Jul 24, 2026
afa5cb6
refactor(core): extract inbox activity presentation
richardsolomou Jul 24, 2026
a7e4e28
refactor(core): extract portability contracts
richardsolomou Jul 24, 2026
1f3ad6a
refactor(ui): reuse inbox identifier formatting
richardsolomou Jul 24, 2026
0c3e6fb
refactor(mobile): adopt shared task runtime
richardsolomou Jul 24, 2026
5299c52
fix(mobile): preserve permission mode on resume
richardsolomou Jul 24, 2026
4892f7f
chore: merge main into composer adoption
richardsolomou Jul 29, 2026
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
2 changes: 2 additions & 0 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"@expo/ui": "0.2.0-beta.9",
"@modelcontextprotocol/ext-apps": "^1.2.2",
"@modelcontextprotocol/sdk": "^1.29.0",
"@posthog/api-client": "workspace:*",
"@posthog/core": "workspace:*",
"@posthog/shared": "workspace:*",
"@react-native-async-storage/async-storage": "^2.2.0",
"@react-native-community/netinfo": "^12.0.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/app/automation/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Text } from "@components/text";
import { TaskAutomationValidationError } from "@posthog/api-client/posthog-client";
import { Stack, useLocalSearchParams, useRouter } from "expo-router";
import { useState } from "react";
import {
Expand All @@ -10,7 +11,6 @@ import {
ScrollView,
View,
} from "react-native";
import { TaskAutomationValidationError } from "@/features/tasks/api";
import { AutomationDetail } from "@/features/tasks/components/AutomationDetail";
import { AutomationForm } from "@/features/tasks/components/AutomationForm";
import {
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/app/automation/create.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TaskAutomationValidationError } from "@posthog/api-client/posthog-client";
import { getCalendars } from "expo-localization";
import { Stack, useLocalSearchParams, useRouter } from "expo-router";
import { useMemo, useRef, useState } from "react";
Expand All @@ -10,7 +11,6 @@ import {
View,
} from "react-native";
import { Text } from "@/components/text";
import { TaskAutomationValidationError } from "@/features/tasks/api";
import { AutomationForm } from "@/features/tasks/components/AutomationForm";
import { useCreateTaskAutomation } from "@/features/tasks/hooks/useAutomations";
import { useSkillStoreSkill } from "@/features/tasks/skills/hooks";
Expand Down
25 changes: 13 additions & 12 deletions apps/mobile/src/app/task/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Text } from "@components/text";
import {
countUserMessages,
getSessionActivityPhase,
} from "@posthog/core/sessions/sessionActivity";
import { isTaskRunning } from "@posthog/core/tasks/taskArchive";
import type { Task } from "@posthog/shared";
import { useQueryClient } from "@tanstack/react-query";
import * as Haptics from "expo-haptics";
import { useLocalSearchParams, useRouter } from "expo-router";
Expand All @@ -14,7 +20,7 @@ import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller
import Animated, { useAnimatedStyle } from "react-native-reanimated";
import { FloatingBackButton } from "@/components/FloatingBackButton";
import { usePreferencesStore } from "@/features/preferences/stores/preferencesStore";
import { getTask, runTaskInCloud } from "@/features/tasks/api";
import { runTaskInCloud } from "@/features/tasks/api";
import { CustomImageBadge } from "@/features/tasks/components/CustomImageBadge";
import { FloatingTaskHeader } from "@/features/tasks/components/FloatingTaskHeader";
import { PrDiffStatsBadge } from "@/features/tasks/components/PrDiffStatsBadge";
Expand Down Expand Up @@ -51,22 +57,15 @@ import {
} from "@/features/tasks/stores/pendingTaskPromptStore";
import { useTaskSessionStore } from "@/features/tasks/stores/taskSessionStore";
import { useTaskStore } from "@/features/tasks/stores/taskStore";
import type { Task } from "@/features/tasks/types";
import {
confirmStopRun,
isTaskRunning,
} from "@/features/tasks/utils/archiveGuard";
import {
countUserMessages,
getSessionActivityPhase,
} from "@/features/tasks/utils/sessionActivity";
import { confirmStopRun } from "@/features/tasks/utils/archiveGuard";
import { useScreenInsets } from "@/hooks/useScreenInsets";
import {
ANALYTICS_EVENTS,
useActiveTaskAnalyticsContext,
useAnalytics,
} from "@/lib/analytics";
import { logger } from "@/lib/logger";
import { getPostHogApiClient } from "@/lib/posthogApiClient";
import { useThemeColors } from "@/lib/theme";

const log = logger.scope("task-detail");
Expand Down Expand Up @@ -221,7 +220,8 @@ export default function TaskDetailScreen() {
setLoading(true);
setError(null);

getTask(taskId)
getPostHogApiClient()
.getTask(taskId)
.then((fetchedTask) => {
if (cancelled) return;
setTask(fetchedTask);
Expand Down Expand Up @@ -252,7 +252,8 @@ export default function TaskDetailScreen() {
if (retrying) return;

let cancelled = false;
getTask(taskId)
getPostHogApiClient()
.getTask(taskId)
.then((freshTask) => {
if (cancelled) return;
setTask(freshTask);
Expand Down
5 changes: 3 additions & 2 deletions apps/mobile/src/app/task/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
import Animated, { runOnJS, useAnimatedStyle } from "react-native-reanimated";
import { useVoiceRecording } from "@/features/chat";
import { usePreferencesStore } from "@/features/preferences/stores/preferencesStore";
import { createTask, runTaskInCloud } from "@/features/tasks/api";
import { runTaskInCloud } from "@/features/tasks/api";
import { GitHubConnectionPrompt } from "@/features/tasks/components/GitHubConnectionPrompt";
import { GitHubLoadNotice } from "@/features/tasks/components/GitHubLoadNotice";
import { AttachmentSheet } from "@/features/tasks/composer/attachments/AttachmentSheet";
Expand Down Expand Up @@ -80,6 +80,7 @@ import {
} from "@/features/tasks/utils/repositorySelection";
import { useScreenInsets } from "@/hooks/useScreenInsets";
import { logger } from "@/lib/logger";
import { getPostHogApiClient } from "@/lib/posthogApiClient";
import { toRgba, useThemeColors } from "@/lib/theme";

const log = logger.scope("task-create");
Expand Down Expand Up @@ -308,7 +309,7 @@ export default function NewTaskScreen() {
? `Attached: ${attachments[0].fileName}`
: `Attached ${attachments.length} files`);

const task = await createTask({
const task = await getPostHogApiClient().createTask({
description: descriptionText,
title: descriptionText.slice(0, 100),
repository: selection.repository ?? undefined,
Expand Down
7 changes: 5 additions & 2 deletions apps/mobile/src/features/chat/components/ToolMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -659,9 +659,12 @@ function CreateTaskPreview({

try {
// Dynamic import to avoid circular dependency
const { createTask, runTaskInCloud } = await import("../../tasks/api");
const [{ runTaskInCloud }, { getPostHogApiClient }] = await Promise.all([
import("../../tasks/api"),
import("@/lib/posthogApiClient"),
]);

const task = await createTask({
const task = await getPostHogApiClient().createTask({
title: args.title,
description: args.description,
repository: args.repository,
Expand Down
3 changes: 1 addition & 2 deletions apps/mobile/src/features/inbox/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { HttpError } from "@/features/tasks/api";
import { authedFetch, getBaseUrl, getProjectId } from "@/lib/api";
import { authedFetch, getBaseUrl, getProjectId, HttpError } from "@/lib/api";
import { logger } from "@/lib/logger";
import type { DismissalReasonOptionValue } from "./constants";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Text } from "@components/text";
import {
buildReviewerOptions,
reviewerMatchesAvailable,
} from "@posthog/core/inbox/artefacts";
import { MagnifyingGlass } from "phosphor-react-native";
import { useMemo, useState } from "react";
import {
Expand All @@ -14,7 +18,6 @@ import { useScreenInsets } from "@/hooks/useScreenInsets";
import { useThemeColors } from "@/lib/theme";
import { useAvailableSuggestedReviewers } from "../hooks/useInboxReports";
import type { AvailableSuggestedReviewer, SuggestedReviewer } from "../types";
import { buildReviewerOptions, reviewerMatchesAvailable } from "../utils";
import { ReviewerOptionRow } from "./ReviewerOptionRow";

interface EditReviewersSheetProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Text } from "@components/text";
import { buildReviewerOptions } from "@posthog/core/inbox/artefacts";
import { useMemo } from "react";
import {
ActivityIndicator,
Expand All @@ -12,7 +13,6 @@ import { useScreenInsets } from "@/hooks/useScreenInsets";
import { useThemeColors } from "@/lib/theme";
import { useAvailableSuggestedReviewers } from "../hooks/useInboxReports";
import { useInboxFilterStore } from "../stores/inboxFilterStore";
import { buildReviewerOptions } from "../utils";
import { ReviewerOptionRow } from "./ReviewerOptionRow";

interface ReviewerFilterSheetProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Text } from "@components/text";
import {
type ReviewerOption,
reviewerOptionLabel,
} from "@posthog/core/inbox/artefacts";
import { Check } from "phosphor-react-native";
import { Image, Pressable, View } from "react-native";
import { useThemeColors } from "@/lib/theme";
import { type ReviewerOption, reviewerOptionLabel } from "../utils";

interface ReviewerOptionRowProps {
reviewer: ReviewerOption;
Expand Down
10 changes: 5 additions & 5 deletions apps/mobile/src/features/inbox/components/SuggestedReviewers.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Text } from "@components/text";
import {
orderSuggestedReviewers,
reviewerMatchesAvailable,
toSuggestedReviewerWriteContent,
} from "@posthog/core/inbox/artefacts";
import { Eye, Plus, X } from "phosphor-react-native";
import { useMemo, useState } from "react";
import {
Expand All @@ -20,11 +25,6 @@ import type {
SuggestedReviewer,
SuggestedReviewersArtefact,
} from "../types";
import {
orderSuggestedReviewers,
reviewerMatchesAvailable,
toSuggestedReviewerWriteContent,
} from "../utils";
import { EditReviewersSheet } from "./EditReviewersSheet";

export type ReviewerActionExtra = Pick<
Expand Down
5 changes: 3 additions & 2 deletions apps/mobile/src/features/inbox/components/TinderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from "react-native-safe-area-context";
import { MarkdownText } from "@/features/chat/components/MarkdownText";
import { usePreferencesStore } from "@/features/preferences/stores/preferencesStore";
import { createTask, runTaskInCloud } from "@/features/tasks/api";
import { runTaskInCloud } from "@/features/tasks/api";
import { DEFAULT_MODEL } from "@/features/tasks/composer/options";
import type {
CreateTaskOptions,
Expand All @@ -29,6 +29,7 @@ import {
useAnalytics,
} from "@/lib/analytics";
import { logger } from "@/lib/logger";
import { getPostHogApiClient } from "@/lib/posthogApiClient";
import { useThemeColors } from "@/lib/theme";
import { getReportRepository } from "../api";
import { useDismissedReportsStore } from "../stores/dismissedReportsStore";
Expand Down Expand Up @@ -239,7 +240,7 @@ export function TinderView({

// 3. Create the task
const prompt = `Act on this signal report. Investigate the root cause, implement the fix, and open a PR if appropriate.\n\n${report.summary ?? ""}`;
const task = await createTask({
const task = await getPostHogApiClient().createTask({
description: prompt,
title: prompt.slice(0, 255),
repository: match?.repository ?? repo ?? undefined,
Expand Down
14 changes: 0 additions & 14 deletions apps/mobile/src/features/inbox/constants.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
/** Comma-separated statuses for the inbox pipeline (excludes terminal/deleted). */
export const INBOX_PIPELINE_STATUS_FILTER =
"potential,candidate,in_progress,ready,pending_input";

/**
* Status filter for the Archive view — the two terminal, not-in-inbox states:
* `suppressed` (user archived it; restorable) and `resolved` (its
* implementation PR merged; terminal, reference only).
*/
export const INBOX_DISMISSED_STATUS_FILTER = "suppressed,resolved";

/** Polling interval for inbox queries (ms). */
export const INBOX_REFETCH_INTERVAL_MS = 5_000;

/**
* Reasons offered when the user dismisses a signal report.
* Mirrors apps/code/src/shared/dismissalReasons.ts.
Expand Down
22 changes: 10 additions & 12 deletions apps/mobile/src/features/inbox/hooks/useInboxReports.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import {
buildArchiveListOrdering,
buildPriorityFilterParam,
buildSignalReportListOrdering,
buildStatusFilterParam,
buildSuggestedReviewerFilterParam,
INBOX_DISMISSED_STATUS_FILTER,
INBOX_REFETCH_INTERVAL_MS,
} from "@posthog/core/inbox/reportFiltering";
import {
useInfiniteQuery,
useMutation,
Expand All @@ -19,10 +28,6 @@ import {
restoreSignalReport,
updateSignalReportArtefact,
} from "../api";
import {
INBOX_DISMISSED_STATUS_FILTER,
INBOX_REFETCH_INTERVAL_MS,
} from "../constants";
import { useInboxFilterStore } from "../stores/inboxFilterStore";
import type {
AvailableSuggestedReviewersResponse,
Expand All @@ -36,14 +41,7 @@ import type {
SuggestedReviewer,
SuggestedReviewerWriteEntry,
} from "../types";
import {
buildArchiveListOrdering,
buildPriorityFilterParam,
buildSignalReportListOrdering,
buildStatusFilterParam,
buildSuggestedReviewerFilterParam,
isRestorableReport,
} from "../utils";
import { isRestorableReport } from "../utils";

export const inboxKeys = {
all: ["inbox", "signal-reports"] as const,
Expand Down
8 changes: 2 additions & 6 deletions apps/mobile/src/features/inbox/stores/inboxFilterStore.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { INBOX_PIPELINE_STATUSES } from "@posthog/core/inbox/reportFiltering";
import type { SourceProduct } from "@posthog/shared";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { create } from "zustand";
Expand All @@ -18,12 +19,7 @@ type SortDirection = "asc" | "desc";
export type { SourceProduct };

export const DEFAULT_STATUS_FILTER: SignalReportStatus[] = [
"ready",
"pending_input",
"in_progress",
"failed",
"candidate",
"potential",
...INBOX_PIPELINE_STATUSES,
];

interface InboxFilterState {
Expand Down
Loading
Loading