Merge origin/main into dev (second round)
Resolve 21 conflicts from latest main (provider profiles, Windows fixes, 0.1.55-rc.1). Fix all type errors and syntax issues from merge artifacts.
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { AppState, Platform } from "react-native";
|
||||
import { AppState } from "react-native";
|
||||
import { isNative } from "@/constants/platform";
|
||||
|
||||
export function getIsAppActivelyVisible(appState: string = AppState.currentState): boolean {
|
||||
if (appState !== "active") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Alert, Platform } from "react-native";
|
||||
import { Alert } from "react-native";
|
||||
import { getDesktopHost, type DesktopDialogAskOptions } from "@/desktop/host";
|
||||
import { isNative } from "@/constants/platform";
|
||||
|
||||
export interface ConfirmDialogInput {
|
||||
title: string;
|
||||
@@ -49,7 +50,7 @@ async function showNativeConfirmDialog(input: ConfirmDialogInput): Promise<boole
|
||||
}
|
||||
|
||||
function getDesktopApi() {
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return null;
|
||||
}
|
||||
return getDesktopHost();
|
||||
@@ -67,7 +68,7 @@ function buildDesktopAskOptions(input: ConfirmDialogInput): DesktopDialogAskOpti
|
||||
}
|
||||
|
||||
function blurActiveWebElement(): void {
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return;
|
||||
}
|
||||
const activeElement = (globalThis as { document?: Document }).document?.activeElement;
|
||||
@@ -103,7 +104,7 @@ function showWebConfirmDialog(input: ConfirmDialogInput): boolean {
|
||||
}
|
||||
|
||||
export async function confirmDialog(input: ConfirmDialogInput): Promise<boolean> {
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return showNativeConfirmDialog(input);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Platform } from "react-native";
|
||||
import {
|
||||
getIsElectronRuntimeMac,
|
||||
getIsElectronRuntime,
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
} from "@/constants/layout";
|
||||
import { getDesktopWindow } from "@/desktop/electron/window";
|
||||
import { usePanelStore } from "@/stores/panel-store";
|
||||
import { isNative } from "@/constants/platform";
|
||||
|
||||
type RawWindowControlsPadding = {
|
||||
left: number;
|
||||
@@ -23,7 +23,7 @@ function useRawWindowControlsPadding(): RawWindowControlsPadding {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== "web" || !getIsElectronRuntime()) return;
|
||||
if (isNative || !getIsElectronRuntime()) return;
|
||||
|
||||
let disposed = false;
|
||||
let cleanup: (() => void) | undefined;
|
||||
|
||||
@@ -80,9 +80,7 @@ describe("workspace route parsing", () => {
|
||||
|
||||
it("parses workspace open intent from pathname query", () => {
|
||||
expect(
|
||||
parseHostWorkspaceOpenIntentFromPathname(
|
||||
"/h/local/workspace/164?open=agent%3Aagent-1",
|
||||
),
|
||||
parseHostWorkspaceOpenIntentFromPathname("/h/local/workspace/164?open=agent%3Aagent-1"),
|
||||
).toEqual({
|
||||
kind: "agent",
|
||||
agentId: "agent-1",
|
||||
|
||||
@@ -321,7 +321,11 @@ export function buildHostAgentDetailRoute(serverId: string, agentId: string, wor
|
||||
if (!normalizedAgentId) {
|
||||
return "/" as const;
|
||||
}
|
||||
return buildHostWorkspaceOpenRoute(serverId, normalizedWorkspaceId, `agent:${normalizedAgentId}`);
|
||||
return buildHostWorkspaceOpenRoute(
|
||||
serverId,
|
||||
normalizedWorkspaceId,
|
||||
`agent:${normalizedAgentId}`,
|
||||
);
|
||||
}
|
||||
const normalizedServerId = trimNonEmpty(serverId);
|
||||
const normalizedAgentId = trimNonEmpty(agentId);
|
||||
@@ -359,7 +363,7 @@ export function buildHostNewWorkspaceRoute(
|
||||
serverId: string,
|
||||
sourceDirectory: string,
|
||||
options?: { displayName?: string },
|
||||
){
|
||||
) {
|
||||
const base = buildHostRootRoute(serverId);
|
||||
if (base === "/") {
|
||||
return "/" as const;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as Linking from "expo-linking";
|
||||
import { Platform } from "react-native";
|
||||
import { getDesktopHost } from "@/desktop/host";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
|
||||
export async function openExternalUrl(url: string): Promise<void> {
|
||||
if (Platform.OS === "web") {
|
||||
if (isWeb) {
|
||||
const opener = getDesktopHost()?.opener?.openUrl;
|
||||
if (typeof opener === "function") {
|
||||
await opener(url);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Asset } from "expo-asset";
|
||||
import { Platform } from "react-native";
|
||||
import { getDesktopHost } from "@/desktop/host";
|
||||
import { buildNotificationRoute, resolveNotificationTarget } from "./notification-routing";
|
||||
import { isNative } from "@/constants/platform";
|
||||
|
||||
type OsNotificationPayload = {
|
||||
title: string;
|
||||
@@ -80,7 +80,7 @@ async function ensureNotificationPermission(): Promise<boolean> {
|
||||
}
|
||||
|
||||
export async function ensureOsNotificationPermission(): Promise<boolean> {
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return false;
|
||||
}
|
||||
return await ensureNotificationPermission();
|
||||
@@ -154,7 +154,7 @@ function attachWebClickHandler(
|
||||
|
||||
export async function sendOsNotification(payload: OsNotificationPayload): Promise<boolean> {
|
||||
// Mobile/native notifications should be remote push only.
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { ProviderSnapshotEntry, AgentProvider } from "@server/server/agent/agent-sdk-types";
|
||||
import {
|
||||
type AgentModeColorTier,
|
||||
type AgentModeIcon,
|
||||
type AgentProviderDefinition,
|
||||
type AgentProviderModeDefinition,
|
||||
} from "@server/server/agent/provider-manifest";
|
||||
|
||||
function buildProviderModes(entry: ProviderSnapshotEntry): AgentProviderModeDefinition[] {
|
||||
const entryModes = entry.modes ?? [];
|
||||
|
||||
return entryModes.map((mode) => ({
|
||||
...mode,
|
||||
icon: (mode.icon ?? "ShieldCheck") as AgentModeIcon,
|
||||
colorTier: (mode.colorTier ?? "moderate") as AgentModeColorTier,
|
||||
}));
|
||||
}
|
||||
|
||||
export function buildProviderDefinitions(
|
||||
snapshotEntries: ProviderSnapshotEntry[] | undefined,
|
||||
): AgentProviderDefinition[] {
|
||||
if (!snapshotEntries?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return snapshotEntries.map((entry) => ({
|
||||
id: entry.provider,
|
||||
label: entry.label ?? entry.provider,
|
||||
description: entry.description ?? "",
|
||||
defaultModeId: entry.defaultModeId ?? null,
|
||||
modes: buildProviderModes(entry),
|
||||
}));
|
||||
}
|
||||
|
||||
export function resolveProviderLabel(
|
||||
provider: string,
|
||||
snapshotEntries: ProviderSnapshotEntry[] | undefined,
|
||||
): string {
|
||||
return snapshotEntries?.find((entry) => entry.provider === provider)?.label ?? provider;
|
||||
}
|
||||
|
||||
export function resolveProviderDefinition(
|
||||
provider: string,
|
||||
snapshotEntries: ProviderSnapshotEntry[] | undefined,
|
||||
): AgentProviderDefinition | undefined {
|
||||
return buildProviderDefinitions(snapshotEntries).find((definition) => definition.id === provider);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Platform } from "react-native";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
|
||||
type ListenerStats = {
|
||||
adds: number;
|
||||
@@ -92,7 +92,7 @@ const SOURCE_LABEL = "[ScrollJankInvestigation]";
|
||||
function shouldInstall(): boolean {
|
||||
const runtime = globalThis as ScrollInvestigationGlobal;
|
||||
const isDev = Boolean((globalThis as { __DEV__?: boolean }).__DEV__);
|
||||
return Platform.OS === "web" && isDev && !runtime.__PASEO_SCROLL_JANK_INVESTIGATION_DISABLED__;
|
||||
return isWeb && isDev && !runtime.__PASEO_SCROLL_JANK_INVESTIGATION_DISABLED__;
|
||||
}
|
||||
|
||||
function normalizeCapture(options?: AddEventListenerOptions | boolean): boolean {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Platform } from "react-native";
|
||||
import { getIsElectronRuntimeMac } from "@/constants/layout";
|
||||
import type { ShortcutOs } from "@/utils/format-shortcut";
|
||||
import { isNative } from "@/constants/platform";
|
||||
|
||||
export function getShortcutOs(): ShortcutOs {
|
||||
if (Platform.OS !== "web") {
|
||||
if (isNative) {
|
||||
return Platform.OS === "ios" ? "mac" : "non-mac";
|
||||
}
|
||||
if (getIsElectronRuntimeMac()) return "mac";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Asset } from "expo-asset";
|
||||
import { File } from "expo-file-system";
|
||||
import { Platform } from "react-native";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
export { parsePcm16Wav, type Pcm16Wav } from "@/utils/pcm16-wav";
|
||||
|
||||
export const THINKING_TONE_REPEAT_GAP_MS = 350;
|
||||
@@ -11,7 +11,7 @@ async function readThinkingToneArrayBuffer(): Promise<ArrayBuffer> {
|
||||
const toneModule = require("../../assets/audio/thinking-tone.wav");
|
||||
const asset = Asset.fromModule(toneModule);
|
||||
|
||||
if (Platform.OS === "web") {
|
||||
if (isWeb) {
|
||||
const response = await fetch(asset.uri);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch thinking tone asset: ${response.status}`);
|
||||
|
||||
@@ -9,7 +9,9 @@ export type ResolvedWorkspaceScriptLink = {
|
||||
|
||||
function isLoopbackHost(host: string): boolean {
|
||||
const normalizedHost = host.trim().toLowerCase();
|
||||
return normalizedHost === "localhost" || normalizedHost === "127.0.0.1" || normalizedHost === "::1";
|
||||
return (
|
||||
normalizedHost === "localhost" || normalizedHost === "127.0.0.1" || normalizedHost === "::1"
|
||||
);
|
||||
}
|
||||
|
||||
function buildDirectServiceUrl(endpoint: string, port: number): string | null {
|
||||
|
||||
Reference in New Issue
Block a user