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: 2 additions & 2 deletions apps/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@
"node-pty": "1.1.0",
"posthog-node": "^5.35.6",
"radix-themes-tw": "0.2.3",
"react": "19.2.6",
"react-dom": "19.2.6",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-hotkeys-hook": "^4.4.4",
"react-scan": "^0.5.6",
"reflect-metadata": "^0.2.2",
Expand Down
5 changes: 3 additions & 2 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"phosphor-react-native": "^3.0.2",
"posthog-react-native": "^4.18.0",
"posthog-react-native-session-replay": "^1.6.0",
"react": "19.2.6",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.5",
"react-native-keyboard-controller": "1.18.5",
"react-native-reanimated": "~4.1.1",
Expand All @@ -83,7 +84,7 @@
"@types/react-test-renderer": "^19.1.0",
"@vitejs/plugin-react": "^4.7.0",
"react-native-svg-transformer": "^1.5.3",
"react-test-renderer": "^19.2.6",
"react-test-renderer": "19.1.0",
"tailwindcss": "^3.4.18",
"typescript": "~5.9.2",
"vite": "^6.4.1",
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/src/app/(tabs)/inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export default function InboxScreen() {
visibleReports: reports,
totalCount,
filters: {
surface: "mobile",
sourceProductFilter,
statusFilter,
suggestedReviewerFilter,
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,6 +1,5 @@
import { Text } from "@components/text";
import { TaskAutomationValidationError } from "@posthog/api-client/posthog-client";
import { parseSkillTemplateId } from "@posthog/core/automations/automationTemplatePresentation";
import { Stack, useLocalSearchParams, useRouter } from "expo-router";
import { useState } from "react";
import {
Expand All @@ -21,6 +20,7 @@ import {
useUpdateTaskAutomation,
} from "@/features/tasks/hooks/useAutomations";
import { useTask } from "@/features/tasks/hooks/useTasks";
import { parseSkillTemplateId } from "@/features/tasks/skills/skillTemplateIds";
import { useThemeColors } from "@/lib/theme";

export default function AutomationDetailScreen() {
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,5 +1,4 @@
import { TaskAutomationValidationError } from "@posthog/api-client/posthog-client";
import { formatSkillTemplateId } from "@posthog/core/automations/automationTemplatePresentation";
import { getCalendars } from "expo-localization";
import { Stack, useLocalSearchParams, useRouter } from "expo-router";
import { useMemo, useRef, useState } from "react";
Expand All @@ -15,6 +14,7 @@ import { Text } from "@/components/text";
import { AutomationForm } from "@/features/tasks/components/AutomationForm";
import { useCreateTaskAutomation } from "@/features/tasks/hooks/useAutomations";
import { useSkillStoreSkill } from "@/features/tasks/skills/hooks";
import { formatSkillTemplateId } from "@/features/tasks/skills/skillTemplateIds";
import { useScreenInsets } from "@/hooks/useScreenInsets";
import { useThemeColors } from "@/lib/theme";

Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/app/mcp-servers/installation/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Text } from "@components/text";
import type { McpApprovalState } from "@posthog/api-client/types";
import { isStdioMcpServer } from "@posthog/core/mcp-servers/presentation";
import { router, useLocalSearchParams } from "expo-router";
import {
ArrowsClockwise,
Expand Down Expand Up @@ -29,6 +28,7 @@ import {
useUpdateMcpToolApproval,
} from "@/features/mcp/hooks";
import { reauthorizeInstallation } from "@/features/mcp/oauth";
import { isStdioMcpServer } from "@/features/mcp/presentation";
import { getMcpConnectionManager } from "@/features/mcp/service";
import { useScreenInsets } from "@/hooks/useScreenInsets";
import { logger } from "@/lib/logger";
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/app/mcp-servers/template/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Text } from "@components/text";
import { isStdioMcpServer } from "@posthog/core/mcp-servers/presentation";
import { router, useLocalSearchParams } from "expo-router";
import { Lock, Warning } from "phosphor-react-native";
import { useMemo, useState } from "react";
Expand All @@ -18,6 +17,7 @@ import {
useMcpMarketplace,
} from "@/features/mcp/hooks";
import { installTemplateWithOAuth } from "@/features/mcp/oauth";
import { isStdioMcpServer } from "@/features/mcp/presentation";
import { useScreenInsets } from "@/hooks/useScreenInsets";
import { logger } from "@/lib/logger";
import { openExternalUrl } from "@/lib/openExternalUrl";
Expand Down
8 changes: 5 additions & 3 deletions apps/mobile/src/features/inbox/activityLog.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {
attributionLabel,
parseDiffLines,
selectActivityArtefacts,
shortSha,
taskRunLabel,
} from "@posthog/core/inbox/activityLog";
import type { AnySignalReportArtefact } from "@posthog/shared/domain-types";
import { describe, expect, it } from "vitest";
import {
parseDiffLines,
selectActivityArtefacts,
shortSha,
} from "./activityLog";

function commit(id: string, createdAt: string): AnySignalReportArtefact {
return {
Expand Down
44 changes: 44 additions & 0 deletions apps/mobile/src/features/inbox/activityLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { AnySignalReportArtefact } from "@posthog/shared/domain-types";

export type ActivityArtefact = Extract<
AnySignalReportArtefact,
{ type: "commit" | "task_run" }
>;

export function selectActivityArtefacts(
artefacts: AnySignalReportArtefact[],
): ActivityArtefact[] {
return artefacts
.filter(
(artefact): artefact is ActivityArtefact =>
artefact.type === "commit" || artefact.type === "task_run",
)
.sort((left, right) => left.created_at.localeCompare(right.created_at));
}

export function shortSha(sha: string): string {
return sha.slice(0, 12);
}

export type DiffLineKind = "add" | "del" | "hunk" | "context";

export interface DiffLine {
text: string;
kind: DiffLineKind;
}

export function parseDiffLines(diff: string): DiffLine[] {
return diff
.replace(/\n$/, "")
.split("\n")
.map((text) => {
if (text.startsWith("+") && !text.startsWith("+++")) {
return { text, kind: "add" as const };
}
if (text.startsWith("-") && !text.startsWith("---")) {
return { text, kind: "del" as const };
}
if (text.startsWith("@@")) return { text, kind: "hunk" as const };
return { text, kind: "context" as const };
});
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Text } from "@components/text";
import { shortSha } from "@posthog/core/inbox/activityLog";
import type { CommitContent } from "@posthog/shared/domain-types";
import { CaretDown, CaretRight } from "phosphor-react-native";
import { useState } from "react";
import { ActivityIndicator, Pressable, View } from "react-native";
import { useThemeColors } from "@/lib/theme";
import { shortSha } from "../activityLog";
import { useCommitDiff } from "../hooks/useInboxReports";
import { DiffBlock } from "./DiffBlock";

Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/features/inbox/components/DiffBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Text } from "@components/text";
import { parseDiffLines } from "@posthog/core/inbox/activityLog";
import { ScrollView, View } from "react-native";
import { parseDiffLines } from "../activityLog";

const LINE_CLASS: Record<string, string> = {
add: "bg-status-success/15 text-status-success",
Expand Down
7 changes: 2 additions & 5 deletions apps/mobile/src/features/inbox/components/ReportActivity.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { Text } from "@components/text";
import {
type ActivityArtefact,
attributionLabel,
selectActivityArtefacts,
} from "@posthog/core/inbox/activityLog";
import { attributionLabel } from "@posthog/core/inbox/activityLog";
import type { AnySignalReportArtefact } from "@posthog/shared/domain-types";
import { ClockCounterClockwise } from "phosphor-react-native";
import { useMemo } from "react";
import { View } from "react-native";
import { formatRelativeTime } from "@/lib/format";
import { useThemeColors } from "@/lib/theme";
import { type ActivityArtefact, selectActivityArtefacts } from "../activityLog";
import { ArtefactCommit } from "./ArtefactCommit";
import { ArtefactTaskRun } from "./ArtefactTaskRun";

Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/features/inbox/components/TinderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export function TinderView({
const themeColors = useThemeColors();
const router = useRouter();
const insets = useSafeAreaInsets();
const { configOptions, hasLiveConfig } = useCloudTaskConfigOptions("claude");
const { configOptions, isConfigReady } = useCloudTaskConfigOptions("claude");
const model = getModelConfigOption(configOptions).currentValue;

// Store state
Expand Down Expand Up @@ -496,7 +496,7 @@ export function TinderView({
setExpandedReport(null);
}}
className="h-16 w-16 items-center justify-center rounded-full border-2 border-status-success bg-status-success/10 active:bg-status-success/20"
disabled={creating || !hasLiveConfig}
disabled={creating || !isConfigReady}
hitSlop={8}
>
{creating ? (
Expand Down
10 changes: 4 additions & 6 deletions apps/mobile/src/features/inbox/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { buildInboxViewedProperties } from "@posthog/core/inbox/engagement";
import {
buildArchiveListOrdering,
buildPriorityFilterParam,
buildSignalReportListOrdering,
INBOX_PIPELINE_STATUSES,
} from "@posthog/core/inbox/reportFiltering";
import { isRestorableReport } from "@posthog/core/inbox/reportMembership";
import { formatSignalReportSummaryMarkdown } from "@posthog/core/inbox/reportPresentation";
import { dismissalReasonLabel } from "@posthog/shared";
import type {
Expand All @@ -13,11 +15,7 @@ import type {
SignalReportStatus,
} from "@posthog/shared/domain-types";
import { describe, expect, it } from "vitest";
import {
buildInboxViewedProperties,
isRestorableReport,
sourceLine,
} from "./utils";
import { sourceLine } from "./utils";

function signal(source_product: string, source_type: string): Signal {
return {
Expand Down Expand Up @@ -46,7 +44,7 @@ function buildMobileInboxViewedProperties(
return buildInboxViewedProperties({
visibleReports: reports,
totalCount,
filters,
filters: { surface: "mobile", ...filters },
});
}

Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/features/mcp/components/McpServerRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import type {
McpRecommendedServer,
McpServerInstallation,
} from "@posthog/api-client/types";
import { isStdioMcpServer } from "@posthog/core/mcp-servers/presentation";
import { CaretRight, Lock, Warning } from "phosphor-react-native";
import type { ReactNode } from "react";
import { Pressable, View } from "react-native";
import { useThemeColors } from "@/lib/theme";
import { isStdioMcpServer } from "../presentation";
import { ServerIcon } from "./ServerIcon";

interface McpServerRowProps {
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/features/mcp/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type {
McpInstallResponse,
McpServerInstallation,
} from "@posthog/api-client/types";
import { isMcpOAuthRedirect } from "@posthog/core/mcp-servers/presentation";
import * as Linking from "expo-linking";
import * as WebBrowser from "expo-web-browser";
import { getPostHogApiClient } from "@/lib/posthogApiClient";
import { isMcpOAuthRedirect } from "./presentation";

/** Custom URL scheme registered via app.json (`scheme: "posthog"`). The cloud
* bounces the OAuth redirect back to this URL once the provider completes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Text } from "@components/text";
import type { TaskAutomation } from "@posthog/api-client/posthog-client";
import { formatAutomationScheduleSummary } from "@posthog/core/automations/automationSchedule";
import { getAutomationTemplatePresentation } from "@posthog/core/automations/automationTemplatePresentation";
import type { TaskRun } from "@posthog/shared";
import { ActivityIndicator, Pressable, View } from "react-native";
import { getAutomationTemplatePresentation } from "../utils/automationTemplatePresentation";
import { AutomationStatusBadge } from "./AutomationStatusBadge";

interface AutomationDetailProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Text } from "@components/text";
import type { TaskAutomation } from "@posthog/api-client/posthog-client";
import { formatAutomationScheduleSummary } from "@posthog/core/automations/automationSchedule";
import { getAutomationTemplatePresentation } from "@posthog/core/automations/automationTemplatePresentation";
import type { TaskRun } from "@posthog/shared";
import { format, formatDistanceToNow } from "date-fns";
import { memo } from "react";
import { Pressable, View } from "react-native";
import { getAutomationTemplatePresentation } from "../utils/automationTemplatePresentation";
import { AutomationStatusBadge } from "./AutomationStatusBadge";

interface AutomationItemProps {
Expand Down
4 changes: 3 additions & 1 deletion apps/mobile/src/features/tasks/composer/TaskChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,9 @@ export function TaskChatComposer({
reasoning,
});
onModelChange(next.model);
onReasoningChange(next.reasoning);
if (next.reasoning !== reasoning) {
onReasoningChange(next.reasoning);
}
}}
onClose={() => setModelSheetOpen(false)}
options={mobileModelOptions.map((m) => ({
Expand Down
1 change: 1 addition & 0 deletions apps/mobile/src/features/tasks/composer/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe("mobile composer options", () => {
[{ hasContent: true }, "send"],
[{ canStop: true }, "stop"],
[{ isRecording: true }, "mic-stop"],
[{ isRecording: true, canStop: true }, "mic-stop"],
[{}, "mic"],
])("derives the mobile primary action", (overrides, expected) => {
expect(
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/features/tasks/composer/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function resolveComposerPrimaryAction({
allowSendWhileRunning: boolean;
}): ComposerPrimaryAction {
if (disabled || isTranscribing) return "disabled";
if (isRecording) return "mic-stop";
if (canStop && (!allowSendWhileRunning || !hasContent)) return "stop";
if (hasContent && !isRecording) return "send";
return isRecording ? "mic-stop" : "mic";
return hasContent ? "send" : "mic";
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,32 @@ describe("useCloudTaskConfigOptions", () => {
expect(mockGetCloudTaskConfigOptions).toHaveBeenCalledWith("claude");
});

it("replaces a hidden GLM current model with a visible model", async () => {
mockGetCloudTaskConfigOptions.mockResolvedValue([
{
id: "model",
name: "Model",
type: "select",
currentValue: "@cf/zai-org/glm-5.2",
options: [
{ value: "@cf/zai-org/glm-5.2", name: "GLM-5.2" },
{ value: "claude-sonnet-5", name: "Claude Sonnet 5" },
],
category: "model",
description: "Choose a model",
},
] satisfies CloudTaskConfigOption[]);

const result = await renderHook();
await waitForAssertion(() => {
const modelOption = getModelConfigOption(result.current.configOptions);
expect(modelOption.currentValue).toBe("claude-sonnet-5");
expect(modelOption.options.map((option) => option.value)).toEqual([
"claude-sonnet-5",
]);
});
});

it("keeps the shared fallback when unauthenticated", async () => {
mockUseAuthStore.mockImplementation((selector) =>
selector({ oauthAccessToken: null }),
Expand All @@ -117,5 +143,19 @@ describe("useCloudTaskConfigOptions", () => {
getModelConfigOption(result.current.configOptions).currentValue,
).toBe(DEFAULT_GATEWAY_MODEL);
expect(mockGetCloudTaskConfigOptions).not.toHaveBeenCalled();
expect(result.current.isConfigReady).toBe(true);
});

it("makes the shared fallback usable after the live catalog fails", async () => {
mockGetCloudTaskConfigOptions.mockRejectedValue(new Error("offline"));

const result = await renderHook();
await waitForAssertion(() => {
expect(result.current.isConfigReady).toBe(true);
});

expect(
getModelConfigOption(result.current.configOptions).currentValue,
).toBe(DEFAULT_GATEWAY_MODEL);
});
});
Loading
Loading