| ... | ... | @@ -159,11 +159,6 @@ import * as ProjectStore from "./orchestration-v2/ProjectStore.ts"; |
| 159 | 159 | import * as ThreadSearch from "./orchestration-v2/ThreadSearch.ts"; |
| 160 | 160 | import * as OrchestrationEventStore from "./persistence/OrchestrationEventStore.ts"; |
| 161 | 161 | import { userFacingDispatchErrorMessage } from "./orchestration-v2/UserFacingErrors.ts"; |
| 162 | | import { |
| 163 | | observeRpcEffect, |
| 164 | | observeRpcStream, |
| 165 | | observeRpcStreamEffect, |
| 166 | | } from "./observability/RpcInstrumentation.ts"; |
| 167 | 162 | import * as ProviderRegistry from "./provider/ProviderRegistry.ts"; |
| 168 | 163 | import * as ProviderInstanceRegistry from "./provider/ProviderInstanceRegistry.ts"; |
| 169 | 164 | import * as AcpRegistrySupport from "./provider/acp/AcpRegistrySupport.ts"; |
| ... | ... | @@ -215,6 +210,7 @@ import * as BackgroundPolicy from "./background/BackgroundPolicy.ts"; |
| 215 | 210 | import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; |
| 216 | 211 | import { requiredScopeForDeviceList, rpcAuthorizationError } from "./auth/RpcAuthorization.ts"; |
| 217 | 212 | import * as RpcAuthorization from "./auth/RpcAuthorization.ts"; |
| 213 | import { RpcInstrumentation, rpcInstrumentationLayer } from "./observability/RpcInstrumentation.ts"; |
| 218 | 214 | import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts"; |
| 219 | 215 | import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts"; |
| 220 | 216 | import * as ResourceTelemetry from "./resourceTelemetry/ResourceTelemetry.ts"; |
| ... | ... | @@ -541,7 +537,8 @@ function projectFileFailureContext( |
| 541 | 537 | |
| 542 | 538 | const PROVIDER_STATUS_DEBOUNCE_MS = 200; |
| 543 | 539 | |
| 544 | | const ServerWsRpcGroup = WsRpcGroup; |
| 540 | // Middleware added later wraps middleware added earlier, so instrumentation wraps authorization. |
| 541 | const ServerWsRpcGroup = WsRpcGroup.middleware(RpcInstrumentation); |
| 545 | 542 | // When a resuming client's cursor is more than this many events behind the |
| 546 | 543 | // current head, skip the per-event catch-up replay and send a fresh shell |
| 547 | 544 | // snapshot instead. Replaying each intervening event costs a shell refetch; |
| ... | ... | @@ -1808,851 +1805,595 @@ const layerWsRpc = ( |
| 1808 | 1805 | |
| 1809 | 1806 | const handlers = ServerWsRpcGroup.of({ |
| 1810 | 1807 | [ORCHESTRATION_V2_WS_METHODS.dispatchCommand]: (command) => |
| 1811 | | observeRpcEffect( |
| 1812 | | ORCHESTRATION_V2_WS_METHODS.dispatchCommand, |
| 1813 | | startup |
| 1814 | | .enqueueCommand( |
| 1815 | | // A retry also restarts the preparation work the launch owns. |
| 1816 | | (command.type === "prepared-run.retry" |
| 1817 | | ? threadLaunch.retryPreparation(command) |
| 1818 | | : ThreadMessageIntake.dispatchCommand( |
| 1819 | | ThreadManagementService.withCreationProvenance(command, { |
| 1820 | | createdBy: "user", |
| 1821 | | creationSource: |
| 1822 | | "creationSource" in command ? command.creationSource : "web", |
| 1823 | | }), |
| 1824 | | ) |
| 1825 | | ).pipe(Effect.provide(intakeContext)), |
| 1826 | | ) |
| 1827 | | .pipe( |
| 1828 | | Effect.tap(() => recordClientCommandAnalytics(command)), |
| 1829 | | Effect.map((result) => ({ sequence: result.sequence })), |
| 1830 | | Effect.mapError((cause) => { |
| 1831 | | const detail = userFacingDispatchErrorMessage(cause); |
| 1832 | | return new OrchestrationV2DispatchCommandError({ |
| 1833 | | commandId: command.commandId, |
| 1834 | | commandType: command.type, |
| 1835 | | message: detail ?? "Failed to dispatch orchestration V2 command", |
| 1836 | | ...(detail === undefined ? {} : { detail }), |
| 1837 | | cause, |
| 1838 | | }); |
| 1839 | | }), |
| 1840 | | ), |
| 1841 | | { |
| 1842 | | "rpc.aggregate": "orchestrationV2", |
| 1843 | | "orchestration_v2.command_id": command.commandId, |
| 1844 | | "orchestration_v2.command_type": command.type, |
| 1845 | | "orchestration_v2.thread_id": |
| 1846 | | command.type === "thread.fork" || command.type === "thread.merge_back" |
| 1847 | | ? command.targetThreadId |
| 1848 | | : command.type === "delegated_task.request" || |
| 1849 | | command.type === "delegated_task.wake-policy" || |
| 1850 | | command.type === "delegated_task.completion-delivery.acknowledge" || |
| 1851 | | command.type === "delegated_task.completion-delivery.dispose" || |
| 1852 | | command.type === "thread.created.record" |
| 1853 | | ? command.parentThreadId |
| 1854 | | : command.threadId, |
| 1855 | | ...(command.type === "thread.fork" || command.type === "thread.merge_back" |
| 1856 | | ? { "orchestration_v2.source_thread_id": command.sourceThreadId } |
| 1857 | | : {}), |
| 1858 | | }, |
| 1808 | Effect.annotateCurrentSpan({ |
| 1809 | "orchestration_v2.command_id": command.commandId, |
| 1810 | "orchestration_v2.command_type": command.type, |
| 1811 | "orchestration_v2.thread_id": |
| 1812 | command.type === "thread.fork" || command.type === "thread.merge_back" |
| 1813 | ? command.targetThreadId |
| 1814 | : command.type === "delegated_task.request" || |
| 1815 | command.type === "delegated_task.wake-policy" || |
| 1816 | command.type === "delegated_task.completion-delivery.acknowledge" || |
| 1817 | command.type === "delegated_task.completion-delivery.dispose" || |
| 1818 | command.type === "thread.created.record" |
| 1819 | ? command.parentThreadId |
| 1820 | : command.threadId, |
| 1821 | ...(command.type === "thread.fork" || command.type === "thread.merge_back" |
| 1822 | ? { "orchestration_v2.source_thread_id": command.sourceThreadId } |
| 1823 | : {}), |
| 1824 | }).pipe( |
| 1825 | Effect.andThen( |
| 1826 | startup |
| 1827 | .enqueueCommand( |
| 1828 | // A retry also restarts the preparation work the launch owns. |
| 1829 | (command.type === "prepared-run.retry" |
| 1830 | ? threadLaunch.retryPreparation(command) |
| 1831 | : ThreadMessageIntake.dispatchCommand( |
| 1832 | ThreadManagementService.withCreationProvenance(command, { |
| 1833 | createdBy: "user", |
| 1834 | creationSource: |
| 1835 | "creationSource" in command ? command.creationSource : "web", |
| 1836 | }), |
| 1837 | ) |
| 1838 | ).pipe(Effect.provide(intakeContext)), |
| 1839 | ) |
| 1840 | .pipe( |
| 1841 | Effect.tap(() => recordClientCommandAnalytics(command)), |
| 1842 | Effect.map((result) => ({ sequence: result.sequence })), |
| 1843 | Effect.mapError((cause) => { |
| 1844 | const detail = userFacingDispatchErrorMessage(cause); |
| 1845 | return new OrchestrationV2DispatchCommandError({ |
| 1846 | commandId: command.commandId, |
| 1847 | commandType: command.type, |
| 1848 | message: detail ?? "Failed to dispatch orchestration V2 command", |
| 1849 | ...(detail === undefined ? {} : { detail }), |
| 1850 | cause, |
| 1851 | }); |
| 1852 | }), |
| 1853 | ), |
| 1854 | ), |
| 1859 | 1855 | ), |
| 1860 | 1856 | [ORCHESTRATION_V2_WS_METHODS.getWorkflowScript]: (input) => |
| 1861 | | observeRpcEffect( |
| 1862 | | ORCHESTRATION_V2_WS_METHODS.getWorkflowScript, |
| 1863 | | readWorkflowScript({ scriptPath: input.scriptPath }), |
| 1864 | | { "rpc.aggregate": "orchestration" }, |
| 1865 | | ), |
| 1857 | readWorkflowScript({ scriptPath: input.scriptPath }), |
| 1866 | 1858 | [ORCHESTRATION_V2_WS_METHODS.getTurnItem]: (input) => |
| 1867 | | observeRpcEffect( |
| 1868 | | ORCHESTRATION_V2_WS_METHODS.getTurnItem, |
| 1869 | | threadManagement.getTurnItem(input).pipe( |
| 1870 | | Effect.mapError( |
| 1871 | | (cause) => |
| 1872 | | new OrchestrationV2GetThreadProjectionError({ |
| 1873 | | threadId: input.threadId, |
| 1874 | | message: "Failed to load turn item", |
| 1875 | | cause, |
| 1876 | | }), |
| 1877 | | ), |
| 1859 | threadManagement.getTurnItem(input).pipe( |
| 1860 | Effect.mapError( |
| 1861 | (cause) => |
| 1862 | new OrchestrationV2GetThreadProjectionError({ |
| 1863 | threadId: input.threadId, |
| 1864 | message: "Failed to load turn item", |
| 1865 | cause, |
| 1866 | }), |
| 1878 | 1867 | ), |
| 1879 | | { "rpc.aggregate": "orchestration" }, |
| 1880 | 1868 | ), |
| 1881 | 1869 | [ORCHESTRATION_V2_WS_METHODS.getTurnDiff]: (input) => |
| 1882 | | observeRpcEffect( |
| 1883 | | ORCHESTRATION_V2_WS_METHODS.getTurnDiff, |
| 1884 | | checkpointDiffQuery.getTurnDiff(input).pipe( |
| 1885 | | Effect.mapError( |
| 1886 | | (cause) => |
| 1887 | | new OrchestrationGetTurnDiffError({ |
| 1888 | | message: "Failed to load turn diff", |
| 1889 | | cause, |
| 1890 | | }), |
| 1891 | | ), |
| 1870 | checkpointDiffQuery.getTurnDiff(input).pipe( |
| 1871 | Effect.mapError( |
| 1872 | (cause) => |
| 1873 | new OrchestrationGetTurnDiffError({ |
| 1874 | message: "Failed to load turn diff", |
| 1875 | cause, |
| 1876 | }), |
| 1892 | 1877 | ), |
| 1893 | | { "rpc.aggregate": "orchestration" }, |
| 1894 | 1878 | ), |
| 1895 | 1879 | [ORCHESTRATION_V2_WS_METHODS.getFullThreadDiff]: (input) => |
| 1896 | | observeRpcEffect( |
| 1897 | | ORCHESTRATION_V2_WS_METHODS.getFullThreadDiff, |
| 1898 | | checkpointDiffQuery.getFullThreadDiff(input).pipe( |
| 1899 | | Effect.mapError( |
| 1900 | | (cause) => |
| 1901 | | new OrchestrationGetFullThreadDiffError({ |
| 1902 | | message: "Failed to load full thread diff", |
| 1903 | | cause, |
| 1904 | | }), |
| 1905 | | ), |
| 1880 | checkpointDiffQuery.getFullThreadDiff(input).pipe( |
| 1881 | Effect.mapError( |
| 1882 | (cause) => |
| 1883 | new OrchestrationGetFullThreadDiffError({ |
| 1884 | message: "Failed to load full thread diff", |
| 1885 | cause, |
| 1886 | }), |
| 1906 | 1887 | ), |
| 1907 | | { "rpc.aggregate": "orchestration" }, |
| 1908 | 1888 | ), |
| 1909 | 1889 | [ORCHESTRATION_V2_WS_METHODS.searchThreads]: (input) => |
| 1910 | | observeRpcEffect( |
| 1911 | | ORCHESTRATION_V2_WS_METHODS.searchThreads, |
| 1912 | | threadSearch.search(input).pipe( |
| 1913 | | Effect.mapError( |
| 1914 | | (cause) => |
| 1915 | | new OrchestrationSearchThreadsError({ |
| 1916 | | message: "Failed to search threads", |
| 1917 | | cause, |
| 1918 | | }), |
| 1919 | | ), |
| 1890 | threadSearch.search(input).pipe( |
| 1891 | Effect.mapError( |
| 1892 | (cause) => |
| 1893 | new OrchestrationSearchThreadsError({ |
| 1894 | message: "Failed to search threads", |
| 1895 | cause, |
| 1896 | }), |
| 1920 | 1897 | ), |
| 1921 | | { "rpc.aggregate": "orchestration" }, |
| 1922 | 1898 | ), |
| 1923 | 1899 | [ORCHESTRATION_V2_WS_METHODS.getArchivedShellSnapshot]: (_input) => |
| 1924 | | observeRpcEffect( |
| 1925 | | ORCHESTRATION_V2_WS_METHODS.getArchivedShellSnapshot, |
| 1926 | | getOrchestrationV2ArchivedShellSnapshot, |
| 1927 | | { "rpc.aggregate": "orchestration" }, |
| 1928 | | ), |
| 1900 | getOrchestrationV2ArchivedShellSnapshot, |
| 1929 | 1901 | [ORCHESTRATION_V2_WS_METHODS.getThreadProjection]: (input) => |
| 1930 | | observeRpcEffect( |
| 1931 | | ORCHESTRATION_V2_WS_METHODS.getThreadProjection, |
| 1932 | | // Pre-pagination clients still call this compatibility endpoint. |
| 1933 | | // Keep stale clients from materializing an unbounded transcript. |
| 1934 | | threadManagement |
| 1935 | | .getThreadSnapshotWindow(input.threadId, { |
| 1936 | | rowLimit: THREAD_HISTORY_SNAPSHOT_ROW_LIMIT, |
| 1937 | | }) |
| 1938 | | .pipe( |
| 1939 | | Effect.map((snapshot) => |
| 1940 | | projectThreadProjectionForWire( |
| 1941 | | buildBoundedThreadProjection({ |
| 1942 | | projection: snapshot.projection, |
| 1943 | | snapshotSequence: snapshot.snapshotSequence, |
| 1944 | | }).projection, |
| 1902 | Effect.annotateCurrentSpan({ "orchestration_v2.thread_id": input.threadId }).pipe( |
| 1903 | Effect.andThen( |
| 1904 | // Pre-pagination clients still call this compatibility endpoint. |
| 1905 | // Keep stale clients from materializing an unbounded transcript. |
| 1906 | threadManagement |
| 1907 | .getThreadSnapshotWindow(input.threadId, { |
| 1908 | rowLimit: THREAD_HISTORY_SNAPSHOT_ROW_LIMIT, |
| 1909 | }) |
| 1910 | .pipe( |
| 1911 | Effect.map((snapshot) => |
| 1912 | projectThreadProjectionForWire( |
| 1913 | buildBoundedThreadProjection({ |
| 1914 | projection: snapshot.projection, |
| 1915 | snapshotSequence: snapshot.snapshotSequence, |
| 1916 | }).projection, |
| 1917 | ), |
| 1918 | ), |
| 1919 | Effect.mapError( |
| 1920 | (cause) => |
| 1921 | new OrchestrationV2GetThreadProjectionError({ |
| 1922 | threadId: input.threadId, |
| 1923 | message: `Failed to load orchestration V2 thread ${input.threadId}`, |
| 1924 | cause, |
| 1925 | }), |
| 1945 | 1926 | ), |
| 1946 | 1927 | ), |
| 1947 | | Effect.mapError( |
| 1948 | | (cause) => |
| 1949 | | new OrchestrationV2GetThreadProjectionError({ |
| 1950 | | threadId: input.threadId, |
| 1951 | | message: `Failed to load orchestration V2 thread ${input.threadId}`, |
| 1952 | | cause, |
| 1953 | | }), |
| 1954 | | ), |
| 1955 | | ), |
| 1956 | | { |
| 1957 | | "rpc.aggregate": "orchestrationV2", |
| 1958 | | "orchestration_v2.thread_id": input.threadId, |
| 1959 | | }, |
| 1928 | ), |
| 1960 | 1929 | ), |
| 1961 | 1930 | [ORCHESTRATION_V2_WS_METHODS.launchThread]: (input) => |
| 1962 | | observeRpcEffect( |
| 1963 | | ORCHESTRATION_V2_WS_METHODS.launchThread, |
| 1964 | | startup |
| 1965 | | .enqueueCommand( |
| 1966 | | ThreadMessageIntake.launchThread({ |
| 1967 | | commandId: input.commandId, |
| 1968 | | ...(input.threadId === undefined ? {} : { threadId: input.threadId }), |
| 1969 | | ...(input.reuseExistingThread === undefined |
| 1970 | | ? {} |
| 1971 | | : { reuseExistingThread: input.reuseExistingThread }), |
| 1972 | | projectId: input.projectId, |
| 1973 | | title: input.title, |
| 1974 | | ...(input.generateTitle === undefined |
| 1975 | | ? {} |
| 1976 | | : { generateTitle: input.generateTitle }), |
| 1977 | | modelSelection: input.modelSelection, |
| 1978 | | runtimeMode: input.runtimeMode, |
| 1979 | | interactionMode: input.interactionMode, |
| 1980 | | workspaceStrategy: input.workspaceStrategy, |
| 1981 | | ...(input.initialMessage === undefined |
| 1982 | | ? {} |
| 1983 | | : { |
| 1984 | | initialMessage: { |
| 1985 | | ...(input.initialMessage.messageId === undefined |
| 1986 | | ? {} |
| 1987 | | : { messageId: input.initialMessage.messageId }), |
| 1988 | | text: input.initialMessage.text, |
| 1989 | | attachments: input.initialMessage.attachments, |
| 1990 | | ...(input.initialMessage.context === undefined |
| 1991 | | ? {} |
| 1992 | | : { context: input.initialMessage.context }), |
| 1993 | | }, |
| 1994 | | }), |
| 1995 | | createdBy: "user", |
| 1996 | | creationSource: input.creationSource ?? "web", |
| 1997 | | }).pipe(Effect.provide(intakeContext)), |
| 1998 | | ) |
| 1999 | | .pipe( |
| 2000 | | Effect.tap(() => |
| 2001 | | analytics |
| 2002 | | .record("client.thread.started", originProps) |
| 2003 | | .pipe( |
| 2004 | | Effect.andThen( |
| 2005 | | input.initialMessage === undefined |
| 2006 | | ? Effect.void |
| 2007 | | : analytics.record("client.turn.requested", originProps), |
| 1931 | Effect.annotateCurrentSpan({ |
| 1932 | "orchestration_v2.command_id": input.commandId, |
| 1933 | "orchestration_v2.project_id": input.projectId, |
| 1934 | }).pipe( |
| 1935 | Effect.andThen( |
| 1936 | startup |
| 1937 | .enqueueCommand( |
| 1938 | ThreadMessageIntake.launchThread({ |
| 1939 | commandId: input.commandId, |
| 1940 | ...(input.threadId === undefined ? {} : { threadId: input.threadId }), |
| 1941 | ...(input.reuseExistingThread === undefined |
| 1942 | ? {} |
| 1943 | : { reuseExistingThread: input.reuseExistingThread }), |
| 1944 | projectId: input.projectId, |
| 1945 | title: input.title, |
| 1946 | ...(input.generateTitle === undefined |
| 1947 | ? {} |
| 1948 | : { generateTitle: input.generateTitle }), |
| 1949 | modelSelection: input.modelSelection, |
| 1950 | runtimeMode: input.runtimeMode, |
| 1951 | interactionMode: input.interactionMode, |
| 1952 | workspaceStrategy: input.workspaceStrategy, |
| 1953 | ...(input.initialMessage === undefined |
| 1954 | ? {} |
| 1955 | : { |
| 1956 | initialMessage: { |
| 1957 | ...(input.initialMessage.messageId === undefined |
| 1958 | ? {} |
| 1959 | : { messageId: input.initialMessage.messageId }), |
| 1960 | text: input.initialMessage.text, |
| 1961 | attachments: input.initialMessage.attachments, |
| 1962 | ...(input.initialMessage.context === undefined |
| 1963 | ? {} |
| 1964 | : { context: input.initialMessage.context }), |
| 1965 | }, |
| 1966 | }), |
| 1967 | createdBy: "user", |
| 1968 | creationSource: input.creationSource ?? "web", |
| 1969 | }).pipe(Effect.provide(intakeContext)), |
| 1970 | ) |
| 1971 | .pipe( |
| 1972 | Effect.tap(() => |
| 1973 | analytics |
| 1974 | .record("client.thread.started", originProps) |
| 1975 | .pipe( |
| 1976 | Effect.andThen( |
| 1977 | input.initialMessage === undefined |
| 1978 | ? Effect.void |
| 1979 | : analytics.record("client.turn.requested", originProps), |
| 1980 | ), |
| 1981 | Effect.ignore, |
| 2008 | 1982 | ), |
| 2009 | | Effect.ignore, |
| 2010 | | ), |
| 1983 | ), |
| 1984 | Effect.map((result) => ({ |
| 1985 | ...result, |
| 1986 | projection: projectThreadProjectionForWire(result.projection), |
| 1987 | })), |
| 1988 | Effect.catchTags({ |
| 1989 | AttachmentClaimError: (cause) => |
| 1990 | new OrchestrationV2ThreadLaunchError({ |
| 1991 | commandId: input.commandId, |
| 1992 | projectId: input.projectId, |
| 1993 | message: cause.message, |
| 1994 | cause, |
| 1995 | }), |
| 1996 | ThreadLaunchError: (cause) => |
| 1997 | new OrchestrationV2ThreadLaunchError({ |
| 1998 | commandId: input.commandId, |
| 1999 | projectId: input.projectId, |
| 2000 | message: "Failed to launch thread", |
| 2001 | cause, |
| 2002 | }), |
| 2003 | ServerRuntimeStartupError: (cause) => |
| 2004 | new OrchestrationV2ThreadLaunchError({ |
| 2005 | commandId: input.commandId, |
| 2006 | projectId: input.projectId, |
| 2007 | message: "Failed to launch thread", |
| 2008 | cause, |
| 2009 | }), |
| 2010 | }), |
| 2011 | 2011 | ), |
| 2012 | | Effect.map((result) => ({ |
| 2013 | | ...result, |
| 2014 | | projection: projectThreadProjectionForWire(result.projection), |
| 2015 | | })), |
| 2016 | | Effect.catchTags({ |
| 2017 | | AttachmentClaimError: (cause) => |
| 2018 | | new OrchestrationV2ThreadLaunchError({ |
| 2019 | | commandId: input.commandId, |
| 2020 | | projectId: input.projectId, |
| 2021 | | message: cause.message, |
| 2022 | | cause, |
| 2023 | | }), |
| 2024 | | ThreadLaunchError: (cause) => |
| 2025 | | new OrchestrationV2ThreadLaunchError({ |
| 2026 | | commandId: input.commandId, |
| 2027 | | projectId: input.projectId, |
| 2028 | | message: "Failed to launch thread", |
| 2029 | | cause, |
| 2030 | | }), |
| 2031 | | ServerRuntimeStartupError: (cause) => |
| 2032 | | new OrchestrationV2ThreadLaunchError({ |
| 2033 | | commandId: input.commandId, |
| 2034 | | projectId: input.projectId, |
| 2035 | | message: "Failed to launch thread", |
| 2036 | | cause, |
| 2037 | | }), |
| 2038 | | }), |
| 2039 | | ), |
| 2040 | | { |
| 2041 | | "rpc.aggregate": "orchestration", |
| 2042 | | "orchestration_v2.command_id": input.commandId, |
| 2043 | | "orchestration_v2.project_id": input.projectId, |
| 2044 | | }, |
| 2012 | ), |
| 2045 | 2013 | ), |
| 2046 | 2014 | [ORCHESTRATION_V2_WS_METHODS.subscribeArchivedShell]: (_input) => |
| 2047 | | observeRpcStreamEffect( |
| 2048 | | ORCHESTRATION_V2_WS_METHODS.subscribeArchivedShell, |
| 2049 | | subscribeOrchestrationV2ArchivedShell(), |
| 2050 | | { "rpc.aggregate": "orchestration" }, |
| 2051 | | ), |
| 2015 | Stream.unwrap(subscribeOrchestrationV2ArchivedShell()), |
| 2052 | 2016 | [ORCHESTRATION_V2_WS_METHODS.subscribeShell]: (input) => |
| 2053 | | observeRpcStreamEffect( |
| 2054 | | ORCHESTRATION_V2_WS_METHODS.subscribeShell, |
| 2055 | | subscribeOrchestrationV2Shell(input), |
| 2056 | | { |
| 2057 | | "rpc.aggregate": "orchestrationV2", |
| 2058 | | }, |
| 2059 | | ), |
| 2017 | Stream.unwrap(subscribeOrchestrationV2Shell(input)), |
| 2060 | 2018 | [ORCHESTRATION_V2_WS_METHODS.subscribeThread]: (input) => |
| 2061 | | observeRpcStreamEffect( |
| 2062 | | ORCHESTRATION_V2_WS_METHODS.subscribeThread, |
| 2063 | | subscribeOrchestrationV2Thread(input), |
| 2064 | | { |
| 2065 | | "rpc.aggregate": "orchestrationV2", |
| 2066 | | "orchestration_v2.thread_id": input.threadId, |
| 2067 | | }, |
| 2019 | Stream.unwrap( |
| 2020 | Effect.annotateCurrentSpan({ "orchestration_v2.thread_id": input.threadId }).pipe( |
| 2021 | Effect.andThen(subscribeOrchestrationV2Thread(input)), |
| 2022 | ), |
| 2068 | 2023 | ), |
| 2069 | 2024 | [WS_METHODS.scheduledTasksList]: (_input) => |
| 2070 | | observeRpcEffect( |
| 2071 | | WS_METHODS.scheduledTasksList, |
| 2072 | | scheduledTasks.list().pipe(Effect.map(withVisibleWebhookUrls)), |
| 2073 | | { "rpc.aggregate": "scheduledTasks" }, |
| 2074 | | ), |
| 2025 | scheduledTasks.list().pipe(Effect.map(withVisibleWebhookUrls)), |
| 2075 | 2026 | [WS_METHODS.scheduledTasksSubscribe]: (_input) => |
| 2076 | | observeRpcStream( |
| 2077 | | WS_METHODS.scheduledTasksSubscribe, |
| 2078 | | scheduledTasks.subscribeList().pipe(Stream.map(withVisibleWebhookUrls)), |
| 2079 | | { "rpc.aggregate": "scheduledTasks" }, |
| 2080 | | ), |
| 2081 | | [WS_METHODS.scheduledTasksUpsert]: (input) => |
| 2082 | | observeRpcEffect(WS_METHODS.scheduledTasksUpsert, scheduledTasks.upsert(input), { |
| 2083 | | "rpc.aggregate": "scheduledTasks", |
| 2084 | | }), |
| 2027 | scheduledTasks.subscribeList().pipe(Stream.map(withVisibleWebhookUrls)), |
| 2028 | [WS_METHODS.scheduledTasksUpsert]: (input) => scheduledTasks.upsert(input), |
| 2085 | 2029 | [WS_METHODS.scheduledTasksSetEnabled]: (input) => |
| 2086 | | observeRpcEffect(WS_METHODS.scheduledTasksSetEnabled, scheduledTasks.setEnabled(input), { |
| 2087 | | "rpc.aggregate": "scheduledTasks", |
| 2088 | | "scheduled_task.id": input.id, |
| 2089 | | }), |
| 2030 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2031 | Effect.andThen(scheduledTasks.setEnabled(input)), |
| 2032 | ), |
| 2090 | 2033 | [WS_METHODS.scheduledTasksDelete]: (input) => |
| 2091 | | observeRpcEffect(WS_METHODS.scheduledTasksDelete, scheduledTasks.delete(input), { |
| 2092 | | "rpc.aggregate": "scheduledTasks", |
| 2093 | | "scheduled_task.id": input.id, |
| 2094 | | }), |
| 2034 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2035 | Effect.andThen(scheduledTasks.delete(input)), |
| 2036 | ), |
| 2095 | 2037 | [WS_METHODS.scheduledTasksRunNow]: (input) => |
| 2096 | | observeRpcEffect(WS_METHODS.scheduledTasksRunNow, scheduledTasks.runNow(input), { |
| 2097 | | "rpc.aggregate": "scheduledTasks", |
| 2098 | | "scheduled_task.id": input.id, |
| 2099 | | }), |
| 2038 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2039 | Effect.andThen(scheduledTasks.runNow(input)), |
| 2040 | ), |
| 2100 | 2041 | [WS_METHODS.scheduledTasksRotateWebhookToken]: (input) => |
| 2101 | | observeRpcEffect( |
| 2102 | | WS_METHODS.scheduledTasksRotateWebhookToken, |
| 2103 | | scheduledTasks.rotateWebhookToken(input), |
| 2104 | | { "rpc.aggregate": "scheduledTasks", "scheduled_task.id": input.id }, |
| 2042 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2043 | Effect.andThen(scheduledTasks.rotateWebhookToken(input)), |
| 2105 | 2044 | ), |
| 2106 | 2045 | [WS_METHODS.secretsAnswerRequest]: (input) => |
| 2107 | | observeRpcEffect(WS_METHODS.secretsAnswerRequest, secretRequests.answer(input), { |
| 2108 | | "rpc.aggregate": "secrets", |
| 2109 | | "orchestration_v2.thread_id": input.threadId, |
| 2110 | | }), |
| 2046 | Effect.annotateCurrentSpan({ "orchestration_v2.thread_id": input.threadId }).pipe( |
| 2047 | Effect.andThen(secretRequests.answer(input)), |
| 2048 | ), |
| 2111 | 2049 | [WS_METHODS.scheduledTasksListWebhookDeliveries]: (input) => |
| 2112 | | observeRpcEffect( |
| 2113 | | WS_METHODS.scheduledTasksListWebhookDeliveries, |
| 2114 | | scheduledTasks.listWebhookDeliveries(input), |
| 2115 | | { "rpc.aggregate": "scheduledTasks", "scheduled_task.id": input.id }, |
| 2050 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2051 | Effect.andThen(scheduledTasks.listWebhookDeliveries(input)), |
| 2116 | 2052 | ), |
| 2117 | 2053 | [WS_METHODS.scheduledTasksGetWebhookDelivery]: (input) => |
| 2118 | | observeRpcEffect( |
| 2119 | | WS_METHODS.scheduledTasksGetWebhookDelivery, |
| 2120 | | scheduledTasks.getWebhookDelivery(input), |
| 2121 | | { "rpc.aggregate": "scheduledTasks", "scheduled_task.id": input.id }, |
| 2122 | | ), |
| 2123 | | [WS_METHODS.serverProbe]: (_input) => |
| 2124 | | observeRpcEffect(WS_METHODS.serverProbe, Effect.succeed({}), { |
| 2125 | | "rpc.aggregate": "server", |
| 2126 | | }), |
| 2127 | | [WS_METHODS.serverGetConfig]: (_input) => |
| 2128 | | observeRpcEffect( |
| 2129 | | WS_METHODS.serverGetConfig, |
| 2130 | | loadServerConfig({ usageLimitsCommand: false }), |
| 2131 | | { |
| 2132 | | "rpc.aggregate": "server", |
| 2133 | | }, |
| 2054 | Effect.annotateCurrentSpan({ "scheduled_task.id": input.id }).pipe( |
| 2055 | Effect.andThen(scheduledTasks.getWebhookDelivery(input)), |
| 2134 | 2056 | ), |
| 2057 | [WS_METHODS.serverProbe]: (_input) => Effect.succeed({}), |
| 2058 | [WS_METHODS.serverGetConfig]: (_input) => loadServerConfig({ usageLimitsCommand: false }), |
| 2135 | 2059 | [WS_METHODS.serverSearchAcpRegistry]: (input) => |
| 2136 | | observeRpcEffect( |
| 2137 | | WS_METHODS.serverSearchAcpRegistry, |
| 2138 | | acpRegistryCatalog |
| 2139 | | .search(input) |
| 2140 | | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2141 | | { "rpc.aggregate": "server" }, |
| 2142 | | ), |
| 2060 | acpRegistryCatalog |
| 2061 | .search(input) |
| 2062 | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2143 | 2063 | [WS_METHODS.serverPrepareAcpRegistryAgent]: (input) => |
| 2144 | | observeRpcEffect( |
| 2145 | | WS_METHODS.serverPrepareAcpRegistryAgent, |
| 2146 | | acpRegistryCatalog |
| 2147 | | .prepare(input) |
| 2148 | | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2149 | | { |
| 2150 | | "rpc.aggregate": "server", |
| 2151 | | "acp_registry.agent_id": input.agentId, |
| 2152 | | }, |
| 2064 | Effect.annotateCurrentSpan({ "acp_registry.agent_id": input.agentId }).pipe( |
| 2065 | Effect.andThen( |
| 2066 | acpRegistryCatalog |
| 2067 | .prepare(input) |
| 2068 | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2069 | ), |
| 2153 | 2070 | ), |
| 2154 | 2071 | [WS_METHODS.serverUninstallAcpRegistryManagedBinary]: (input) => |
| 2155 | | observeRpcEffect( |
| 2156 | | WS_METHODS.serverUninstallAcpRegistryManagedBinary, |
| 2157 | | acpRegistryCatalog |
| 2158 | | .uninstallManagedBinary(input) |
| 2159 | | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2160 | | { |
| 2161 | | "rpc.aggregate": "server", |
| 2162 | | "acp_registry.agent_id": input.agentId, |
| 2163 | | }, |
| 2072 | Effect.annotateCurrentSpan({ "acp_registry.agent_id": input.agentId }).pipe( |
| 2073 | Effect.andThen( |
| 2074 | acpRegistryCatalog |
| 2075 | .uninstallManagedBinary(input) |
| 2076 | .pipe(Effect.mapError(AcpRegistrySupport.toAcpRegistryOperationError)), |
| 2077 | ), |
| 2164 | 2078 | ), |
| 2165 | 2079 | [WS_METHODS.serverAcceptAcpRegistryUrlAuth]: (input) => |
| 2166 | | observeRpcEffect( |
| 2167 | | WS_METHODS.serverAcceptAcpRegistryUrlAuth, |
| 2168 | | acpRegistryRuntimeCoordinator |
| 2169 | | .acceptUrlAuthentication(input) |
| 2170 | | .pipe(Effect.map((accepted) => ({ accepted }))), |
| 2171 | | { |
| 2172 | | "rpc.aggregate": "server", |
| 2173 | | "provider.instance_id": input.instanceId, |
| 2174 | | }, |
| 2080 | Effect.annotateCurrentSpan({ "provider.instance_id": input.instanceId }).pipe( |
| 2081 | Effect.andThen( |
| 2082 | acpRegistryRuntimeCoordinator |
| 2083 | .acceptUrlAuthentication(input) |
| 2084 | .pipe(Effect.map((accepted) => ({ accepted }))), |
| 2085 | ), |
| 2175 | 2086 | ), |
| 2176 | 2087 | [WS_METHODS.serverListAcpRegistrySessions]: (input) => |
| 2177 | | observeRpcEffect( |
| 2178 | | WS_METHODS.serverListAcpRegistrySessions, |
| 2179 | | listAcpRegistrySessions(input), |
| 2180 | | { |
| 2181 | | "rpc.aggregate": "server", |
| 2182 | | "provider.instance_id": input.instanceId, |
| 2183 | | "project.id": input.projectId, |
| 2184 | | }, |
| 2185 | | ), |
| 2088 | Effect.annotateCurrentSpan({ |
| 2089 | "provider.instance_id": input.instanceId, |
| 2090 | "project.id": input.projectId, |
| 2091 | }).pipe(Effect.andThen(listAcpRegistrySessions(input))), |
| 2186 | 2092 | [WS_METHODS.serverImportAcpRegistrySession]: (input) => |
| 2187 | | observeRpcEffect( |
| 2188 | | WS_METHODS.serverImportAcpRegistrySession, |
| 2189 | | importAcpRegistrySession(input), |
| 2190 | | { |
| 2191 | | "rpc.aggregate": "server", |
| 2192 | | "provider.instance_id": input.instanceId, |
| 2193 | | "project.id": input.projectId, |
| 2194 | | }, |
| 2195 | | ), |
| 2093 | Effect.annotateCurrentSpan({ |
| 2094 | "provider.instance_id": input.instanceId, |
| 2095 | "project.id": input.projectId, |
| 2096 | }).pipe(Effect.andThen(importAcpRegistrySession(input))), |
| 2196 | 2097 | [WS_METHODS.serverDeleteAcpRegistrySession]: (input) => |
| 2197 | | observeRpcEffect( |
| 2198 | | WS_METHODS.serverDeleteAcpRegistrySession, |
| 2199 | | deleteAcpRegistrySession(input), |
| 2200 | | { |
| 2201 | | "rpc.aggregate": "server", |
| 2202 | | "provider.instance_id": input.instanceId, |
| 2203 | | "project.id": input.projectId, |
| 2204 | | }, |
| 2205 | | ), |
| 2098 | Effect.annotateCurrentSpan({ |
| 2099 | "provider.instance_id": input.instanceId, |
| 2100 | "project.id": input.projectId, |
| 2101 | }).pipe(Effect.andThen(deleteAcpRegistrySession(input))), |
| 2206 | 2102 | [WS_METHODS.serverListAcpRegistryProviders]: (input) => |
| 2207 | | observeRpcEffect( |
| 2208 | | WS_METHODS.serverListAcpRegistryProviders, |
| 2209 | | listAcpRegistryProviders(input), |
| 2210 | | { |
| 2211 | | "rpc.aggregate": "server", |
| 2212 | | "provider.instance_id": input.instanceId, |
| 2213 | | "project.id": input.projectId, |
| 2214 | | }, |
| 2215 | | ), |
| 2103 | Effect.annotateCurrentSpan({ |
| 2104 | "provider.instance_id": input.instanceId, |
| 2105 | "project.id": input.projectId, |
| 2106 | }).pipe(Effect.andThen(listAcpRegistryProviders(input))), |
| 2216 | 2107 | [WS_METHODS.serverSetAcpRegistryProvider]: (input) => |
| 2217 | | observeRpcEffect(WS_METHODS.serverSetAcpRegistryProvider, setAcpRegistryProvider(input), { |
| 2218 | | "rpc.aggregate": "server", |
| 2108 | Effect.annotateCurrentSpan({ |
| 2219 | 2109 | "provider.instance_id": input.instanceId, |
| 2220 | 2110 | "project.id": input.projectId, |
| 2221 | | }), |
| 2111 | }).pipe(Effect.andThen(setAcpRegistryProvider(input))), |
| 2222 | 2112 | [WS_METHODS.serverDisableAcpRegistryProvider]: (input) => |
| 2223 | | observeRpcEffect( |
| 2224 | | WS_METHODS.serverDisableAcpRegistryProvider, |
| 2225 | | disableAcpRegistryProvider(input), |
| 2226 | | { |
| 2227 | | "rpc.aggregate": "server", |
| 2228 | | "provider.instance_id": input.instanceId, |
| 2229 | | "project.id": input.projectId, |
| 2230 | | }, |
| 2231 | | ), |
| 2113 | Effect.annotateCurrentSpan({ |
| 2114 | "provider.instance_id": input.instanceId, |
| 2115 | "project.id": input.projectId, |
| 2116 | }).pipe(Effect.andThen(disableAcpRegistryProvider(input))), |
| 2232 | 2117 | [WS_METHODS.serverLogoutAcpRegistry]: (input) => |
| 2233 | | observeRpcEffect( |
| 2234 | | WS_METHODS.serverLogoutAcpRegistry, |
| 2235 | | Effect.gen(function* () { |
| 2236 | | const { instance, manager } = yield* acpSessionManager(input.instanceId); |
| 2237 | | const snapshot = yield* instance.snapshot.getSnapshot; |
| 2238 | | if (snapshot.auth.canLogout !== true) { |
| 2239 | | return yield* new AcpRegistryOperationError({ |
| 2240 | | reason: "logout_unsupported", |
| 2241 | | message: "The ACP agent does not advertise logout.", |
| 2242 | | }); |
| 2243 | | } |
| 2244 | | if (instance.auth) { |
| 2245 | | yield* providerAuth.logout(input).pipe( |
| 2246 | | Effect.mapError( |
| 2247 | | (cause) => |
| 2248 | | new AcpRegistryOperationError({ |
| 2249 | | reason: "logout_failed", |
| 2250 | | message: "Could not sign out of the ACP agent.", |
| 2251 | | cause, |
| 2252 | | }), |
| 2253 | | ), |
| 2254 | | ); |
| 2255 | | } else { |
| 2256 | | yield* providerSessionManager.closeInstance(input.instanceId).pipe( |
| 2257 | | Effect.mapError( |
| 2258 | | (cause) => |
| 2259 | | new AcpRegistryOperationError({ |
| 2260 | | reason: "logout_failed", |
| 2261 | | message: "Could not stop live sessions before ACP logout.", |
| 2262 | | cause, |
| 2263 | | }), |
| 2264 | | ), |
| 2265 | | ); |
| 2266 | | yield* manager.logout(config.cwd); |
| 2267 | | } |
| 2268 | | yield* providerRegistry.refreshInstance(input.instanceId); |
| 2269 | | return { loggedOut: true } as const; |
| 2270 | | }), |
| 2271 | | { |
| 2272 | | "rpc.aggregate": "server", |
| 2273 | | "provider.instance_id": input.instanceId, |
| 2274 | | }, |
| 2275 | | ), |
| 2276 | | [WS_METHODS.serverRefreshProviders]: (input) => |
| 2277 | | observeRpcEffect( |
| 2278 | | WS_METHODS.serverRefreshProviders, |
| 2279 | | Effect.gen(function* () { |
| 2280 | | // Only explicit catalog refreshes bypass T3's caches. Workspace |
| 2281 | | // discovery and background status checks retain their timers. |
| 2282 | | if (input.refreshModels) { |
| 2283 | | yield* modelManifest.forceRefresh; |
| 2284 | | const instances = yield* providerInstances.listInstances; |
| 2285 | | yield* Effect.forEach( |
| 2286 | | instances.filter( |
| 2287 | | (instance) => |
| 2288 | | input.instanceId === undefined || input.instanceId === instance.instanceId, |
| 2289 | | ), |
| 2290 | | (instance) => |
| 2291 | | Effect.gen(function* () { |
| 2292 | | yield* instance.invalidateCaches ?? Effect.void; |
| 2293 | | const maintenance = yield* instance.snapshot.resolveMaintenance({ |
| 2294 | | fresh: true, |
| 2295 | | }); |
| 2296 | | if (maintenance.packageName) |
| 2297 | | providerVersionCache.delete(maintenance.packageName); |
| 2298 | | }), |
| 2299 | | { concurrency: "unbounded", discard: true }, |
| 2300 | | ); |
| 2301 | | } |
| 2302 | | // An untargeted refresh is "re-read everything's status", which |
| 2303 | | // includes quota from configured usage-limit sources. Awaited, |
| 2304 | | // not forked: the RPC scope closes on return and would |
| 2305 | | // interrupt a fork before the hub answered. |
| 2306 | | if (input.instanceId === undefined) { |
| 2307 | | yield* usageLimitSources.refresh; |
| 2308 | | } |
| 2309 | | let providers = yield* input.cwd !== undefined && input.instanceId !== undefined |
| 2310 | | ? providerRegistry.refreshWorkspaceSnapshot({ |
| 2311 | | instanceId: input.instanceId, |
| 2312 | | cwd: input.cwd, |
| 2313 | | fresh: input.fresh === true, |
| 2314 | | }) |
| 2315 | | : input.instanceId !== undefined |
| 2316 | | ? providerRegistry.refreshInstance(input.instanceId) |
| 2317 | | : providerRegistry.refresh(); |
| 2318 | | if (input.refreshModels) { |
| 2319 | | const instances = yield* providerInstances.listInstances; |
| 2320 | | for (const instance of instances) { |
| 2321 | | if ( |
| 2322 | | !instance.refreshModels || |
| 2323 | | (input.instanceId !== undefined && input.instanceId !== instance.instanceId) || |
| 2324 | | !providers.some( |
| 2325 | | (provider) => |
| 2326 | | provider.instanceId === instance.instanceId && |
| 2327 | | provider.enabled && |
| 2328 | | provider.installed, |
| 2329 | | ) |
| 2330 | | ) |
| 2331 | | continue; |
| 2332 | | yield* instance.refreshModels().pipe( |
| 2118 | Effect.annotateCurrentSpan({ "provider.instance_id": input.instanceId }).pipe( |
| 2119 | Effect.andThen( |
| 2120 | Effect.gen(function* () { |
| 2121 | const { instance, manager } = yield* acpSessionManager(input.instanceId); |
| 2122 | const snapshot = yield* instance.snapshot.getSnapshot; |
| 2123 | if (snapshot.auth.canLogout !== true) { |
| 2124 | return yield* new AcpRegistryOperationError({ |
| 2125 | reason: "logout_unsupported", |
| 2126 | message: "The ACP agent does not advertise logout.", |
| 2127 | }); |
| 2128 | } |
| 2129 | if (instance.auth) { |
| 2130 | yield* providerAuth.logout(input).pipe( |
| 2131 | Effect.mapError( |
| 2132 | (cause) => |
| 2133 | new AcpRegistryOperationError({ |
| 2134 | reason: "logout_failed", |
| 2135 | message: "Could not sign out of the ACP agent.", |
| 2136 | cause, |
| 2137 | }), |
| 2138 | ), |
| 2139 | ); |
| 2140 | } else { |
| 2141 | yield* providerSessionManager.closeInstance(input.instanceId).pipe( |
| 2333 | 2142 | Effect.mapError( |
| 2334 | | (error) => |
| 2335 | | new ProviderSetupError({ |
| 2336 | | instanceId: instance.instanceId, |
| 2337 | | operation: "refresh-models", |
| 2338 | | detail: error.detail, |
| 2143 | (cause) => |
| 2144 | new AcpRegistryOperationError({ |
| 2145 | reason: "logout_failed", |
| 2146 | message: "Could not stop live sessions before ACP logout.", |
| 2147 | cause, |
| 2339 | 2148 | }), |
| 2340 | 2149 | ), |
| 2341 | 2150 | ); |
| 2342 | | providers = yield* providerRegistry.refreshInstance(instance.instanceId); |
| 2151 | yield* manager.logout(config.cwd); |
| 2343 | 2152 | } |
| 2344 | | } |
| 2345 | | return { providers }; |
| 2346 | | }), |
| 2347 | | { "rpc.aggregate": "server" }, |
| 2153 | yield* providerRegistry.refreshInstance(input.instanceId); |
| 2154 | return { loggedOut: true } as const; |
| 2155 | }), |
| 2156 | ), |
| 2348 | 2157 | ), |
| 2349 | | [WS_METHODS.providerUploadFeedback]: (input) => |
| 2350 | | observeRpcEffect( |
| 2351 | | WS_METHODS.providerUploadFeedback, |
| 2352 | | Effect.gen(function* () { |
| 2353 | | const projection = yield* threadManagement.getThreadRecords(input.threadId, [ |
| 2354 | | "providerThreads", |
| 2355 | | ]); |
| 2356 | | const providerThread = |
| 2357 | | projection.providerThreads.find( |
| 2358 | | (candidate) => candidate.id === projection.thread.activeProviderThreadId, |
| 2359 | | ) ?? projection.providerThreads.at(-1); |
| 2360 | | const providerSessionId = providerThread?.providerSessionId ?? null; |
| 2361 | | if (providerThread === undefined || providerSessionId === null) { |
| 2362 | | return yield* Effect.fail( |
| 2363 | | new ProviderUploadFeedbackError({ |
| 2364 | | threadId: input.threadId, |
| 2365 | | cause: "No provider session has run in this thread yet.", |
| 2158 | [WS_METHODS.serverRefreshProviders]: (input) => |
| 2159 | Effect.gen(function* () { |
| 2160 | // Only explicit catalog refreshes bypass T3's caches. Workspace |
| 2161 | // discovery and background status checks retain their timers. |
| 2162 | if (input.refreshModels) { |
| 2163 | yield* modelManifest.forceRefresh; |
| 2164 | const instances = yield* providerInstances.listInstances; |
| 2165 | yield* Effect.forEach( |
| 2166 | instances.filter( |
| 2167 | (instance) => |
| 2168 | input.instanceId === undefined || input.instanceId === instance.instanceId, |
| 2169 | ), |
| 2170 | (instance) => |
| 2171 | Effect.gen(function* () { |
| 2172 | yield* instance.invalidateCaches ?? Effect.void; |
| 2173 | const maintenance = yield* instance.snapshot.resolveMaintenance({ |
| 2174 | fresh: true, |
| 2175 | }); |
| 2176 | if (maintenance.packageName) |
| 2177 | providerVersionCache.delete(maintenance.packageName); |
| 2366 | 2178 | }), |
| 2179 | { concurrency: "unbounded", discard: true }, |
| 2180 | ); |
| 2181 | } |
| 2182 | // An untargeted refresh is "re-read everything's status", which |
| 2183 | // includes quota from configured usage-limit sources. Awaited, |
| 2184 | // not forked: the RPC scope closes on return and would |
| 2185 | // interrupt a fork before the hub answered. |
| 2186 | if (input.instanceId === undefined) { |
| 2187 | yield* usageLimitSources.refresh; |
| 2188 | } |
| 2189 | let providers = yield* input.cwd !== undefined && input.instanceId !== undefined |
| 2190 | ? providerRegistry.refreshWorkspaceSnapshot({ |
| 2191 | instanceId: input.instanceId, |
| 2192 | cwd: input.cwd, |
| 2193 | fresh: input.fresh === true, |
| 2194 | }) |
| 2195 | : input.instanceId !== undefined |
| 2196 | ? providerRegistry.refreshInstance(input.instanceId) |
| 2197 | : providerRegistry.refresh(); |
| 2198 | if (input.refreshModels) { |
| 2199 | const instances = yield* providerInstances.listInstances; |
| 2200 | for (const instance of instances) { |
| 2201 | if ( |
| 2202 | !instance.refreshModels || |
| 2203 | (input.instanceId !== undefined && input.instanceId !== instance.instanceId) || |
| 2204 | !providers.some( |
| 2205 | (provider) => |
| 2206 | provider.instanceId === instance.instanceId && |
| 2207 | provider.enabled && |
| 2208 | provider.installed, |
| 2209 | ) |
| 2210 | ) |
| 2211 | continue; |
| 2212 | yield* instance.refreshModels().pipe( |
| 2213 | Effect.mapError( |
| 2214 | (error) => |
| 2215 | new ProviderSetupError({ |
| 2216 | instanceId: instance.instanceId, |
| 2217 | operation: "refresh-models", |
| 2218 | detail: error.detail, |
| 2219 | }), |
| 2220 | ), |
| 2367 | 2221 | ); |
| 2222 | providers = yield* providerRegistry.refreshInstance(instance.instanceId); |
| 2368 | 2223 | } |
| 2369 | | const runtime = Option.getOrNull(yield* providerSessionsV2.get(providerSessionId)); |
| 2370 | | if (runtime === null) { |
| 2371 | | return yield* Effect.fail( |
| 2372 | | new ProviderUploadFeedbackError({ |
| 2224 | } |
| 2225 | return { providers }; |
| 2226 | }), |
| 2227 | [WS_METHODS.providerUploadFeedback]: (input) => |
| 2228 | Effect.gen(function* () { |
| 2229 | const projection = yield* threadManagement.getThreadRecords(input.threadId, [ |
| 2230 | "providerThreads", |
| 2231 | ]); |
| 2232 | const providerThread = |
| 2233 | projection.providerThreads.find( |
| 2234 | (candidate) => candidate.id === projection.thread.activeProviderThreadId, |
| 2235 | ) ?? projection.providerThreads.at(-1); |
| 2236 | const providerSessionId = providerThread?.providerSessionId ?? null; |
| 2237 | if (providerThread === undefined || providerSessionId === null) { |
| 2238 | return yield* Effect.fail( |
| 2239 | new ProviderUploadFeedbackError({ |
| 2240 | threadId: input.threadId, |
| 2241 | cause: "No provider session has run in this thread yet.", |
| 2242 | }), |
| 2243 | ); |
| 2244 | } |
| 2245 | const runtime = Option.getOrNull(yield* providerSessionsV2.get(providerSessionId)); |
| 2246 | if (runtime === null) { |
| 2247 | return yield* Effect.fail( |
| 2248 | new ProviderUploadFeedbackError({ |
| 2249 | threadId: input.threadId, |
| 2250 | cause: "The provider session is no longer running. Send a message first.", |
| 2251 | }), |
| 2252 | ); |
| 2253 | } |
| 2254 | if (runtime.uploadFeedback === undefined) { |
| 2255 | return yield* Effect.fail( |
| 2256 | new ProviderUploadFeedbackError({ |
| 2257 | threadId: input.threadId, |
| 2258 | cause: `Provider '${runtime.driver}' does not support feedback uploads.`, |
| 2259 | }), |
| 2260 | ); |
| 2261 | } |
| 2262 | return yield* runtime.uploadFeedback({ |
| 2263 | providerThread, |
| 2264 | ...(input.reason === undefined ? {} : { reason: input.reason }), |
| 2265 | }); |
| 2266 | }).pipe( |
| 2267 | Effect.mapError((cause) => |
| 2268 | isProviderUploadFeedbackError(cause) |
| 2269 | ? cause |
| 2270 | : new ProviderUploadFeedbackError({ |
| 2373 | 2271 | threadId: input.threadId, |
| 2374 | | cause: "The provider session is no longer running. Send a message first.", |
| 2272 | cause, |
| 2375 | 2273 | }), |
| 2376 | | ); |
| 2377 | | } |
| 2378 | | if (runtime.uploadFeedback === undefined) { |
| 2379 | | return yield* Effect.fail( |
| 2380 | | new ProviderUploadFeedbackError({ |
| 2381 | | threadId: input.threadId, |
| 2382 | | cause: `Provider '${runtime.driver}' does not support feedback uploads.`, |
| 2383 | | }), |
| 2384 | | ); |
| 2385 | | } |
| 2386 | | return yield* runtime.uploadFeedback({ |
| 2387 | | providerThread, |
| 2388 | | ...(input.reason === undefined ? {} : { reason: input.reason }), |
| 2389 | | }); |
| 2390 | | }).pipe( |
| 2391 | | Effect.mapError((cause) => |
| 2392 | | isProviderUploadFeedbackError(cause) |
| 2393 | | ? cause |
| 2394 | | : new ProviderUploadFeedbackError({ |
| 2395 | | threadId: input.threadId, |
| 2396 | | cause, |
| 2397 | | }), |
| 2398 | | ), |
| 2399 | 2274 | ), |
| 2400 | | { "rpc.aggregate": "provider" }, |
| 2401 | 2275 | ), |
| 2402 | 2276 | [WS_METHODS.serverUpdateProvider]: (input) => |
| 2403 | | observeRpcEffect( |
| 2404 | | WS_METHODS.serverUpdateProvider, |
| 2405 | | providerMaintenanceRunner.updateProvider(input), |
| 2406 | | { |
| 2407 | | "rpc.aggregate": "server", |
| 2408 | | }, |
| 2409 | | ), |
| 2277 | providerMaintenanceRunner.updateProvider(input), |
| 2410 | 2278 | [WS_METHODS.providerConsumeResetCredit]: (input) => |
| 2411 | | observeRpcEffect( |
| 2412 | | WS_METHODS.providerConsumeResetCredit, |
| 2413 | | Effect.gen(function* () { |
| 2414 | | if ("sourceId" in input) return yield* usageLimitSources.consumeResetCredit(input); |
| 2415 | | const instance = yield* providerInstances.getInstance(input.instanceId); |
| 2416 | | // A disabled instance must not spend anything on its account. |
| 2417 | | if (instance === undefined || !instance.enabled) { |
| 2418 | | return yield* new ProviderSetupError({ |
| 2419 | | instanceId: input.instanceId, |
| 2420 | | operation: "consume-reset-credit", |
| 2421 | | detail: instance ? "This provider is disabled." : "Provider instance not found.", |
| 2422 | | }); |
| 2423 | | } |
| 2424 | | if (instance.consumeResetCredit === undefined) { |
| 2425 | | return yield* new ProviderSetupError({ |
| 2426 | | instanceId: input.instanceId, |
| 2427 | | operation: "consume-reset-credit", |
| 2428 | | detail: "This provider does not bank reset credits.", |
| 2429 | | }); |
| 2430 | | } |
| 2431 | | const outcome = yield* instance.consumeResetCredit().pipe( |
| 2432 | | Effect.mapError( |
| 2433 | | (error) => |
| 2434 | | new ProviderSetupError({ |
| 2435 | | instanceId: input.instanceId, |
| 2436 | | operation: "consume-reset-credit", |
| 2437 | | detail: error.detail, |
| 2438 | | cause: error, |
| 2439 | | }), |
| 2440 | | ), |
| 2441 | | ); |
| 2442 | | return { outcome }; |
| 2443 | | }), |
| 2444 | | { "rpc.aggregate": "provider" }, |
| 2445 | | ), |
| 2446 | | [WS_METHODS.providerAuthStart]: (input) => |
| 2447 | | observeRpcEffect( |
| 2448 | | WS_METHODS.providerAuthStart, |
| 2449 | | providerAuth.start(input, currentSessionId), |
| 2450 | | { "rpc.aggregate": "provider" }, |
| 2451 | | ), |
| 2279 | Effect.gen(function* () { |
| 2280 | if ("sourceId" in input) return yield* usageLimitSources.consumeResetCredit(input); |
| 2281 | const instance = yield* providerInstances.getInstance(input.instanceId); |
| 2282 | // A disabled instance must not spend anything on its account. |
| 2283 | if (instance === undefined || !instance.enabled) { |
| 2284 | return yield* new ProviderSetupError({ |
| 2285 | instanceId: input.instanceId, |
| 2286 | operation: "consume-reset-credit", |
| 2287 | detail: instance ? "This provider is disabled." : "Provider instance not found.", |
| 2288 | }); |
| 2289 | } |
| 2290 | if (instance.consumeResetCredit === undefined) { |
| 2291 | return yield* new ProviderSetupError({ |
| 2292 | instanceId: input.instanceId, |
| 2293 | operation: "consume-reset-credit", |
| 2294 | detail: "This provider does not bank reset credits.", |
| 2295 | }); |
| 2296 | } |
| 2297 | const outcome = yield* instance.consumeResetCredit().pipe( |
| 2298 | Effect.mapError( |
| 2299 | (error) => |
| 2300 | new ProviderSetupError({ |
| 2301 | instanceId: input.instanceId, |
| 2302 | operation: "consume-reset-credit", |
| 2303 | detail: error.detail, |
| 2304 | cause: error, |
| 2305 | }), |
| 2306 | ), |
| 2307 | ); |
| 2308 | return { outcome }; |
| 2309 | }), |
| 2310 | [WS_METHODS.providerAuthStart]: (input) => providerAuth.start(input, currentSessionId), |
| 2452 | 2311 | [WS_METHODS.providerAuthRespond]: (input) => |
| 2453 | | observeRpcEffect( |
| 2454 | | WS_METHODS.providerAuthRespond, |
| 2455 | | providerAuth.respond(input, currentSessionId), |
| 2456 | | { |
| 2457 | | "rpc.aggregate": "provider", |
| 2458 | | instanceId: input.instanceId, |
| 2459 | | }, |
| 2312 | Effect.annotateCurrentSpan({ instanceId: input.instanceId }).pipe( |
| 2313 | Effect.andThen(providerAuth.respond(input, currentSessionId)), |
| 2460 | 2314 | ), |
| 2461 | 2315 | [WS_METHODS.providerAuthComplete]: (input) => |
| 2462 | | observeRpcEffect( |
| 2463 | | WS_METHODS.providerAuthComplete, |
| 2464 | | providerAuth.complete(input, currentSessionId), |
| 2465 | | { "rpc.aggregate": "provider" }, |
| 2466 | | ), |
| 2316 | providerAuth.complete(input, currentSessionId), |
| 2467 | 2317 | [WS_METHODS.chatGptReconnectProfile]: (input) => providerAuth.reconnectProfile(input), |
| 2468 | 2318 | [WS_METHODS.chatGptImportProfile]: (input) => providerAuth.importProfile(input), |
| 2469 | 2319 | [WS_METHODS.chatGptHandoffSubscribe]: (input) => |
| 2470 | 2320 | subscribeChatGptHandoff(input, currentSessionId), |
| 2471 | | [WS_METHODS.codexAuthCallbackSubscribe]: (input) => |
| 2472 | | observeRpcStream( |
| 2473 | | WS_METHODS.codexAuthCallbackSubscribe, |
| 2474 | | subscribeCodexAuthCallback(input), |
| 2475 | | { |
| 2476 | | "rpc.aggregate": "provider", |
| 2477 | | }, |
| 2478 | | ), |
| 2479 | | [WS_METHODS.providerAuthCancel]: (input) => |
| 2480 | | observeRpcEffect( |
| 2481 | | WS_METHODS.providerAuthCancel, |
| 2482 | | providerAuth.cancel(input, currentSessionId), |
| 2483 | | { "rpc.aggregate": "provider" }, |
| 2484 | | ), |
| 2485 | | [WS_METHODS.providerAuthLogout]: (input) => |
| 2486 | | observeRpcEffect(WS_METHODS.providerAuthLogout, providerAuth.logout(input), { |
| 2487 | | "rpc.aggregate": "provider", |
| 2488 | | }), |
| 2321 | [WS_METHODS.codexAuthCallbackSubscribe]: (input) => subscribeCodexAuthCallback(input), |
| 2322 | [WS_METHODS.providerAuthCancel]: (input) => providerAuth.cancel(input, currentSessionId), |
| 2323 | [WS_METHODS.providerAuthLogout]: (input) => providerAuth.logout(input), |
| 2489 | 2324 | [WS_METHODS.providerAuthSubscribe]: (input) => |
| 2490 | | observeRpcStream( |
| 2491 | | WS_METHODS.providerAuthSubscribe, |
| 2492 | | providerAuth.subscribe(input, currentSessionId), |
| 2493 | | { "rpc.aggregate": "provider" }, |
| 2494 | | ), |
| 2495 | | [WS_METHODS.providerInstallStart]: (input) => |
| 2496 | | observeRpcEffect(WS_METHODS.providerInstallStart, providerInstallation.start(input), { |
| 2497 | | "rpc.aggregate": "provider", |
| 2498 | | }), |
| 2499 | | [WS_METHODS.providerInstallCancel]: (input) => |
| 2500 | | observeRpcEffect(WS_METHODS.providerInstallCancel, providerInstallation.cancel(input), { |
| 2501 | | "rpc.aggregate": "provider", |
| 2502 | | }), |
| 2503 | | [WS_METHODS.providerInstallSubscribe]: (input) => |
| 2504 | | observeRpcStream( |
| 2505 | | WS_METHODS.providerInstallSubscribe, |
| 2506 | | providerInstallation.subscribe(input), |
| 2507 | | { "rpc.aggregate": "provider" }, |
| 2508 | | ), |
| 2509 | | [WS_METHODS.providerInstallRemove]: (input) => |
| 2510 | | observeRpcEffect(WS_METHODS.providerInstallRemove, providerInstallation.remove(input), { |
| 2511 | | "rpc.aggregate": "provider", |
| 2512 | | }), |
| 2513 | | [WS_METHODS.serverUpdateServer]: (input) => |
| 2514 | | observeRpcEffect(WS_METHODS.serverUpdateServer, serverSelfUpdate.update(input), { |
| 2515 | | "rpc.aggregate": "server", |
| 2516 | | }), |
| 2325 | providerAuth.subscribe(input, currentSessionId), |
| 2326 | [WS_METHODS.providerInstallStart]: (input) => providerInstallation.start(input), |
| 2327 | [WS_METHODS.providerInstallCancel]: (input) => providerInstallation.cancel(input), |
| 2328 | [WS_METHODS.providerInstallSubscribe]: (input) => providerInstallation.subscribe(input), |
| 2329 | [WS_METHODS.providerInstallRemove]: (input) => providerInstallation.remove(input), |
| 2330 | [WS_METHODS.serverUpdateServer]: (input) => serverSelfUpdate.update(input), |
| 2517 | 2331 | [WS_METHODS.serverUpdateServerWithProgress]: (input) => |
| 2518 | | observeRpcStream( |
| 2519 | | WS_METHODS.serverUpdateServerWithProgress, |
| 2520 | | Stream.callback<ServerSelfUpdateProgressEvent, ServerSelfUpdateError>((queue) => |
| 2521 | | serverSelfUpdate |
| 2522 | | .update(input, (stage) => |
| 2332 | Stream.callback<ServerSelfUpdateProgressEvent, ServerSelfUpdateError>((queue) => |
| 2333 | serverSelfUpdate |
| 2334 | .update(input, (stage) => |
| 2335 | Queue.offer(queue, { |
| 2336 | type: "progress", |
| 2337 | stage, |
| 2338 | }).pipe(Effect.asVoid), |
| 2339 | ) |
| 2340 | .pipe( |
| 2341 | Effect.flatMap((result) => |
| 2523 | 2342 | Queue.offer(queue, { |
| 2524 | | type: "progress", |
| 2525 | | stage, |
| 2526 | | }).pipe(Effect.asVoid), |
| 2527 | | ) |
| 2528 | | .pipe( |
| 2529 | | Effect.flatMap((result) => |
| 2530 | | Queue.offer(queue, { |
| 2531 | | type: "complete", |
| 2532 | | result, |
| 2533 | | }), |
| 2534 | | ), |
| 2535 | | Effect.catchTags({ |
| 2536 | | ServerSelfUpdateError: (error) => Queue.fail(queue, error), |
| 2343 | type: "complete", |
| 2344 | result, |
| 2537 | 2345 | }), |
| 2538 | | Effect.andThen(Queue.end(queue)), |
| 2539 | | Effect.forkScoped, |
| 2540 | 2346 | ), |
| 2541 | | ), |
| 2542 | | { "rpc.aggregate": "server" }, |
| 2347 | Effect.catchTags({ |
| 2348 | ServerSelfUpdateError: (error) => Queue.fail(queue, error), |
| 2349 | }), |
| 2350 | Effect.andThen(Queue.end(queue)), |
| 2351 | Effect.forkScoped, |
| 2352 | ), |
| 2543 | 2353 | ), |
| 2544 | 2354 | [WS_METHODS.serverCommitDesktopUpdate]: (input) => |
| 2545 | | observeRpcEffect( |
| 2546 | | WS_METHODS.serverCommitDesktopUpdate, |
| 2547 | | serverSelfUpdate.commitDesktopUpdate(input.requestId), |
| 2548 | | { "rpc.aggregate": "server" }, |
| 2549 | | ), |
| 2355 | serverSelfUpdate.commitDesktopUpdate(input.requestId), |
| 2550 | 2356 | [WS_METHODS.serverUpsertKeybinding]: (rule) => |
| 2551 | | observeRpcEffect( |
| 2552 | | WS_METHODS.serverUpsertKeybinding, |
| 2553 | | Effect.gen(function* () { |
| 2554 | | const keybindingsConfig = yield* keybindings.upsertKeybindingRule(rule); |
| 2555 | | return { keybindings: keybindingsConfig, issues: [] }; |
| 2556 | | }), |
| 2557 | | { "rpc.aggregate": "server" }, |
| 2558 | | ), |
| 2357 | Effect.gen(function* () { |
| 2358 | const keybindingsConfig = yield* keybindings.upsertKeybindingRule(rule); |
| 2359 | return { keybindings: keybindingsConfig, issues: [] }; |
| 2360 | }), |
| 2559 | 2361 | [WS_METHODS.serverRemoveKeybinding]: (rule) => |
| 2560 | | observeRpcEffect( |
| 2561 | | WS_METHODS.serverRemoveKeybinding, |
| 2562 | | Effect.gen(function* () { |
| 2563 | | const keybindingsConfig = yield* keybindings.removeKeybindingRule(rule); |
| 2564 | | return { keybindings: keybindingsConfig, issues: [] }; |
| 2565 | | }), |
| 2566 | | { "rpc.aggregate": "server" }, |
| 2567 | | ), |
| 2362 | Effect.gen(function* () { |
| 2363 | const keybindingsConfig = yield* keybindings.removeKeybindingRule(rule); |
| 2364 | return { keybindings: keybindingsConfig, issues: [] }; |
| 2365 | }), |
| 2568 | 2366 | [WS_METHODS.serverGetSettings]: (_input) => |
| 2569 | | observeRpcEffect( |
| 2570 | | WS_METHODS.serverGetSettings, |
| 2571 | | serverSettings.getSettings.pipe( |
| 2572 | | Effect.map(ServerSettings.redactServerSettingsForClient), |
| 2573 | | ), |
| 2574 | | { |
| 2575 | | "rpc.aggregate": "server", |
| 2576 | | }, |
| 2577 | | ), |
| 2367 | serverSettings.getSettings.pipe(Effect.map(ServerSettings.redactServerSettingsForClient)), |
| 2578 | 2368 | [WS_METHODS.serverUpdateSettings]: ({ patch, providerInstanceMutation }) => |
| 2579 | | observeRpcEffect( |
| 2580 | | WS_METHODS.serverUpdateSettings, |
| 2581 | | Effect.gen(function* () { |
| 2582 | | const deviceHosts = patch.deviceHosts |
| 2583 | | ? yield* remoteSshDeviceHosts(patch.deviceHosts).pipe( |
| 2584 | | Effect.provide(deviceHostContext), |
| 2585 | | ) |
| 2586 | | : undefined; |
| 2587 | | const nextPatch = { ...patch, ...(deviceHosts ? { deviceHosts } : {}) }; |
| 2588 | | const settings = yield* providerInstanceMutation === undefined |
| 2589 | | ? serverSettings.updateSettings(nextPatch) |
| 2590 | | : serverSettings.updateProviderInstance(providerInstanceMutation, nextPatch); |
| 2591 | | return ServerSettings.redactServerSettingsForClient(settings); |
| 2592 | | }), |
| 2593 | | { |
| 2594 | | "rpc.aggregate": "server", |
| 2595 | | }, |
| 2596 | | ), |
| 2597 | | [WS_METHODS.serverDiscoverSourceControl]: (_input) => |
| 2598 | | observeRpcEffect( |
| 2599 | | WS_METHODS.serverDiscoverSourceControl, |
| 2600 | | sourceControlDiscovery.discover, |
| 2601 | | { |
| 2602 | | "rpc.aggregate": "server", |
| 2603 | | }, |
| 2604 | | ), |
| 2605 | | [WS_METHODS.serverGetTraceDiagnostics]: (_input) => |
| 2606 | | observeRpcEffect( |
| 2607 | | WS_METHODS.serverGetTraceDiagnostics, |
| 2608 | | TraceDiagnostics.readTraceDiagnostics({ |
| 2609 | | traceFilePath: config.serverTracePath, |
| 2610 | | maxFiles: config.traceMaxFiles, |
| 2611 | | }), |
| 2612 | | { |
| 2613 | | "rpc.aggregate": "server", |
| 2614 | | }, |
| 2615 | | ), |
| 2616 | | [WS_METHODS.serverGetProcessDiagnostics]: (_input) => |
| 2617 | | observeRpcEffect(WS_METHODS.serverGetProcessDiagnostics, processDiagnostics.read, { |
| 2618 | | "rpc.aggregate": "server", |
| 2369 | Effect.gen(function* () { |
| 2370 | const deviceHosts = patch.deviceHosts |
| 2371 | ? yield* remoteSshDeviceHosts(patch.deviceHosts).pipe( |
| 2372 | Effect.provide(deviceHostContext), |
| 2373 | ) |
| 2374 | : undefined; |
| 2375 | const nextPatch = { ...patch, ...(deviceHosts ? { deviceHosts } : {}) }; |
| 2376 | const settings = yield* providerInstanceMutation === undefined |
| 2377 | ? serverSettings.updateSettings(nextPatch) |
| 2378 | : serverSettings.updateProviderInstance(providerInstanceMutation, nextPatch); |
| 2379 | return ServerSettings.redactServerSettingsForClient(settings); |
| 2619 | 2380 | }), |
| 2620 | | [WS_METHODS.serverGetHostResources]: (_input) => |
| 2621 | | observeRpcEffect(WS_METHODS.serverGetHostResources, hostResources.read, { |
| 2622 | | "rpc.aggregate": "server", |
| 2381 | [WS_METHODS.serverDiscoverSourceControl]: (_input) => sourceControlDiscovery.discover, |
| 2382 | [WS_METHODS.serverGetTraceDiagnostics]: (_input) => |
| 2383 | TraceDiagnostics.readTraceDiagnostics({ |
| 2384 | traceFilePath: config.serverTracePath, |
| 2385 | maxFiles: config.traceMaxFiles, |
| 2623 | 2386 | }), |
| 2387 | [WS_METHODS.serverGetProcessDiagnostics]: (_input) => processDiagnostics.read, |
| 2388 | [WS_METHODS.serverGetHostResources]: (_input) => hostResources.read, |
| 2624 | 2389 | [WS_METHODS.serverGetProcessResourceHistory]: (input) => |
| 2625 | | observeRpcEffect( |
| 2626 | | WS_METHODS.serverGetProcessResourceHistory, |
| 2627 | | processResourceMonitor.readHistory(input), |
| 2628 | | { |
| 2629 | | "rpc.aggregate": "server", |
| 2630 | | }, |
| 2631 | | ), |
| 2390 | processResourceMonitor.readHistory(input), |
| 2632 | 2391 | [WS_METHODS.serverGetResourceTelemetryHistory]: (input) => |
| 2633 | | observeRpcEffect( |
| 2634 | | WS_METHODS.serverGetResourceTelemetryHistory, |
| 2635 | | resourceTelemetry.readHistory(input), |
| 2636 | | { |
| 2637 | | "rpc.aggregate": "server", |
| 2638 | | }, |
| 2639 | | ), |
| 2640 | | [WS_METHODS.serverGetUsageSummary]: (input) => |
| 2641 | | observeRpcEffect(WS_METHODS.serverGetUsageSummary, usage.readSummary(input), { |
| 2642 | | "rpc.aggregate": "server", |
| 2643 | | }), |
| 2644 | | [WS_METHODS.serverRefreshUsageRates]: (_input) => |
| 2645 | | observeRpcEffect(WS_METHODS.serverRefreshUsageRates, usage.refreshRates, { |
| 2646 | | "rpc.aggregate": "server", |
| 2647 | | }), |
| 2648 | | [WS_METHODS.serverRetryResourceTelemetry]: (_input) => |
| 2649 | | observeRpcEffect(WS_METHODS.serverRetryResourceTelemetry, resourceTelemetry.retry, { |
| 2650 | | "rpc.aggregate": "server", |
| 2651 | | }), |
| 2652 | | [WS_METHODS.serverSignalProcess]: (input) => |
| 2653 | | observeRpcEffect(WS_METHODS.serverSignalProcess, processDiagnostics.signal(input), { |
| 2654 | | "rpc.aggregate": "server", |
| 2655 | | }), |
| 2392 | resourceTelemetry.readHistory(input), |
| 2393 | [WS_METHODS.serverGetUsageSummary]: (input) => usage.readSummary(input), |
| 2394 | [WS_METHODS.serverRefreshUsageRates]: (_input) => usage.refreshRates, |
| 2395 | [WS_METHODS.serverRetryResourceTelemetry]: (_input) => resourceTelemetry.retry, |
| 2396 | [WS_METHODS.serverSignalProcess]: (input) => processDiagnostics.signal(input), |
| 2656 | 2397 | [WS_METHODS.serverReportClientActivity]: (input, metadata) => |
| 2657 | 2398 | Ref.update(rpcClientIds, (clientIds) => { |
| 2658 | 2399 | const next = new Set(clientIds); |
| ... | ... | @@ -2660,583 +2401,303 @@ const layerWsRpc = ( |
| 2660 | 2401 | return next; |
| 2661 | 2402 | }).pipe( |
| 2662 | 2403 | Effect.andThen( |
| 2663 | | observeRpcEffect( |
| 2664 | | WS_METHODS.serverReportClientActivity, |
| 2665 | | backgroundPolicy.reportClientActivity( |
| 2666 | | currentSessionId, |
| 2667 | | RpcClientId.make(metadata.client.id), |
| 2668 | | input, |
| 2669 | | ), |
| 2670 | | { "rpc.aggregate": "server" }, |
| 2404 | backgroundPolicy.reportClientActivity( |
| 2405 | currentSessionId, |
| 2406 | RpcClientId.make(metadata.client.id), |
| 2407 | input, |
| 2671 | 2408 | ), |
| 2672 | 2409 | ), |
| 2673 | 2410 | ), |
| 2674 | 2411 | [WS_METHODS.serverReportHostPowerState]: (input) => |
| 2675 | | observeRpcEffect( |
| 2676 | | WS_METHODS.serverReportHostPowerState, |
| 2677 | | backgroundPolicy.reportHostPowerState(input), |
| 2678 | | { "rpc.aggregate": "server" }, |
| 2679 | | ), |
| 2680 | | [WS_METHODS.serverGetBackgroundPolicy]: (_input) => |
| 2681 | | observeRpcEffect(WS_METHODS.serverGetBackgroundPolicy, backgroundPolicy.snapshot, { |
| 2682 | | "rpc.aggregate": "server", |
| 2683 | | }), |
| 2684 | | [WS_METHODS.cloudGetRelayClientStatus]: (_input) => |
| 2685 | | observeRpcEffect(WS_METHODS.cloudGetRelayClientStatus, relayClient.resolve, { |
| 2686 | | "rpc.aggregate": "cloud", |
| 2687 | | }), |
| 2412 | backgroundPolicy.reportHostPowerState(input), |
| 2413 | [WS_METHODS.serverGetBackgroundPolicy]: (_input) => backgroundPolicy.snapshot, |
| 2414 | [WS_METHODS.cloudGetRelayClientStatus]: (_input) => relayClient.resolve, |
| 2688 | 2415 | [WS_METHODS.cloudInstallRelayClient]: (_input) => |
| 2689 | | observeRpcStream( |
| 2690 | | WS_METHODS.cloudInstallRelayClient, |
| 2691 | | Stream.callback<RelayClientInstallProgressEvent, RelayClientInstallFailedError>( |
| 2692 | | (queue) => |
| 2693 | | relayClient |
| 2694 | | .installWithProgress((event) => Queue.offer(queue, event).pipe(Effect.asVoid)) |
| 2695 | | .pipe( |
| 2696 | | Effect.flatMap((status) => |
| 2697 | | Queue.offer(queue, { |
| 2698 | | type: "complete", |
| 2699 | | status, |
| 2416 | Stream.callback<RelayClientInstallProgressEvent, RelayClientInstallFailedError>((queue) => |
| 2417 | relayClient |
| 2418 | .installWithProgress((event) => Queue.offer(queue, event).pipe(Effect.asVoid)) |
| 2419 | .pipe( |
| 2420 | Effect.flatMap((status) => |
| 2421 | Queue.offer(queue, { |
| 2422 | type: "complete", |
| 2423 | status, |
| 2424 | }), |
| 2425 | ), |
| 2426 | Effect.catchTags({ |
| 2427 | RelayClientInstallError: (error) => |
| 2428 | Queue.fail( |
| 2429 | queue, |
| 2430 | new RelayClientInstallFailedError({ |
| 2431 | reason: error.reason, |
| 2432 | message: error.message, |
| 2700 | 2433 | }), |
| 2701 | 2434 | ), |
| 2702 | | Effect.catchTags({ |
| 2703 | | RelayClientInstallError: (error) => |
| 2704 | | Queue.fail( |
| 2705 | | queue, |
| 2706 | | new RelayClientInstallFailedError({ |
| 2707 | | reason: error.reason, |
| 2708 | | message: error.message, |
| 2709 | | }), |
| 2710 | | ), |
| 2711 | | }), |
| 2712 | | Effect.andThen(Queue.end(queue)), |
| 2713 | | Effect.forkScoped, |
| 2714 | | ), |
| 2715 | | ), |
| 2716 | | { "rpc.aggregate": "cloud" }, |
| 2717 | | ), |
| 2718 | | [WS_METHODS.pullRequestsList]: (input) => |
| 2719 | | observeRpcEffect(WS_METHODS.pullRequestsList, pullRequests.list(input), { |
| 2720 | | "rpc.aggregate": "pull-requests", |
| 2721 | | }), |
| 2722 | | [WS_METHODS.pullRequestsListStats]: (input) => |
| 2723 | | observeRpcEffect(WS_METHODS.pullRequestsListStats, pullRequests.listStats(input), { |
| 2724 | | "rpc.aggregate": "pull-requests", |
| 2725 | | }), |
| 2726 | | [WS_METHODS.pullRequestsRoutingIdentity]: (input) => |
| 2727 | | observeRpcEffect( |
| 2728 | | WS_METHODS.pullRequestsRoutingIdentity, |
| 2729 | | pullRequests.routingIdentity(input), |
| 2730 | | { |
| 2731 | | "rpc.aggregate": "pull-requests", |
| 2732 | | }, |
| 2435 | }), |
| 2436 | Effect.andThen(Queue.end(queue)), |
| 2437 | Effect.forkScoped, |
| 2438 | ), |
| 2733 | 2439 | ), |
| 2734 | | [WS_METHODS.pullRequestsRouting]: (input) => |
| 2735 | | observeRpcEffect(WS_METHODS.pullRequestsRouting, pullRequests.routing(input), { |
| 2736 | | "rpc.aggregate": "pull-requests", |
| 2737 | | }), |
| 2440 | [WS_METHODS.pullRequestsList]: (input) => pullRequests.list(input), |
| 2441 | [WS_METHODS.pullRequestsListStats]: (input) => pullRequests.listStats(input), |
| 2442 | [WS_METHODS.pullRequestsRoutingIdentity]: (input) => pullRequests.routingIdentity(input), |
| 2443 | [WS_METHODS.pullRequestsRouting]: (input) => pullRequests.routing(input), |
| 2738 | 2444 | [WS_METHODS.pullRequestsSummary]: (input) => |
| 2739 | | observeRpcEffect( |
| 2740 | | WS_METHODS.pullRequestsSummary, |
| 2741 | | withPullRequestViewer(input, pullRequests.summary(input)), |
| 2742 | | { |
| 2743 | | "rpc.aggregate": "pull-requests", |
| 2744 | | }, |
| 2745 | | ), |
| 2445 | withPullRequestViewer(input, pullRequests.summary(input)), |
| 2746 | 2446 | [WS_METHODS.pullRequestsStack]: (input) => |
| 2747 | | observeRpcEffect( |
| 2748 | | WS_METHODS.pullRequestsStack, |
| 2749 | | withPullRequestViewer(input, pullRequests.stack(input)), |
| 2750 | | { |
| 2751 | | "rpc.aggregate": "pull-requests", |
| 2752 | | }, |
| 2753 | | ), |
| 2447 | withPullRequestViewer(input, pullRequests.stack(input)), |
| 2754 | 2448 | [WS_METHODS.pullRequestsLinkedThreads]: (input) => |
| 2755 | | observeRpcEffect( |
| 2756 | | WS_METHODS.pullRequestsLinkedThreads, |
| 2757 | | resolvePullRequestSyncKey(input).pipe( |
| 2758 | | Effect.flatMap((key) => |
| 2759 | | key === null |
| 2760 | | ? Effect.succeed({ threads: [] }) |
| 2761 | | : listLinkedPullRequestThreads(key).pipe( |
| 2762 | | Effect.provideService(SqlClient.SqlClient, sql), |
| 2763 | | ), |
| 2764 | | ), |
| 2449 | resolvePullRequestSyncKey(input).pipe( |
| 2450 | Effect.flatMap((key) => |
| 2451 | key === null |
| 2452 | ? Effect.succeed({ threads: [] }) |
| 2453 | : listLinkedPullRequestThreads(key).pipe( |
| 2454 | Effect.provideService(SqlClient.SqlClient, sql), |
| 2455 | ), |
| 2765 | 2456 | ), |
| 2766 | | { "rpc.aggregate": "pull-requests" }, |
| 2767 | 2457 | ), |
| 2768 | 2458 | [WS_METHODS.pullRequestsDetail]: (input) => |
| 2769 | | observeRpcEffect( |
| 2770 | | WS_METHODS.pullRequestsDetail, |
| 2771 | | withPullRequestViewer(input, pullRequests.detail(input)), |
| 2772 | | { |
| 2773 | | "rpc.aggregate": "pull-requests", |
| 2774 | | }, |
| 2775 | | ), |
| 2459 | withPullRequestViewer(input, pullRequests.detail(input)), |
| 2776 | 2460 | [WS_METHODS.pullRequestsPreview]: (input) => |
| 2777 | | observeRpcEffect( |
| 2778 | | WS_METHODS.pullRequestsPreview, |
| 2779 | | withPullRequestViewer(input, pullRequests.preview(input)), |
| 2780 | | { "rpc.aggregate": "pull-requests" }, |
| 2781 | | ), |
| 2461 | withPullRequestViewer(input, pullRequests.preview(input)), |
| 2782 | 2462 | [WS_METHODS.pullRequestsChecks]: (input) => |
| 2783 | | observeRpcEffect( |
| 2784 | | WS_METHODS.pullRequestsChecks, |
| 2785 | | withPullRequestViewer(input, pullRequests.checks(input)), |
| 2786 | | { "rpc.aggregate": "pull-requests" }, |
| 2787 | | ), |
| 2463 | withPullRequestViewer(input, pullRequests.checks(input)), |
| 2788 | 2464 | [WS_METHODS.pullRequestsActivity]: (input) => |
| 2789 | | observeRpcEffect( |
| 2790 | | WS_METHODS.pullRequestsActivity, |
| 2791 | | withPullRequestViewer(input, pullRequests.activity(input)), |
| 2792 | | { |
| 2793 | | "rpc.aggregate": "pull-requests", |
| 2794 | | }, |
| 2795 | | ), |
| 2465 | withPullRequestViewer(input, pullRequests.activity(input)), |
| 2796 | 2466 | [WS_METHODS.pullRequestsThreadComments]: (input) => |
| 2797 | | observeRpcEffect( |
| 2798 | | WS_METHODS.pullRequestsThreadComments, |
| 2799 | | withPullRequestViewer(input, pullRequests.threadComments(input)), |
| 2800 | | { |
| 2801 | | "rpc.aggregate": "pull-requests", |
| 2802 | | }, |
| 2803 | | ), |
| 2467 | withPullRequestViewer(input, pullRequests.threadComments(input)), |
| 2804 | 2468 | [WS_METHODS.pullRequestsDiffFileContents]: (input) => |
| 2805 | | observeRpcEffect( |
| 2806 | | WS_METHODS.pullRequestsDiffFileContents, |
| 2807 | | withPullRequestViewer(input, pullRequests.diffFileContents(input)), |
| 2808 | | { "rpc.aggregate": "pull-requests" }, |
| 2809 | | ), |
| 2469 | withPullRequestViewer(input, pullRequests.diffFileContents(input)), |
| 2810 | 2470 | [WS_METHODS.pullRequestsFilesViewed]: (input) => |
| 2811 | | observeRpcEffect( |
| 2812 | | WS_METHODS.pullRequestsFilesViewed, |
| 2813 | | withPullRequestViewer(input, pullRequests.filesViewed(input)), |
| 2814 | | { "rpc.aggregate": "pull-requests" }, |
| 2815 | | ), |
| 2471 | withPullRequestViewer(input, pullRequests.filesViewed(input)), |
| 2816 | 2472 | [WS_METHODS.pullRequestsSetFilesViewed]: (input) => |
| 2817 | | observeRpcEffect( |
| 2818 | | WS_METHODS.pullRequestsSetFilesViewed, |
| 2819 | | withPullRequestViewer(input, pullRequests.setFilesViewed(input)), |
| 2820 | | { "rpc.aggregate": "pull-requests" }, |
| 2821 | | ), |
| 2473 | withPullRequestViewer(input, pullRequests.setFilesViewed(input)), |
| 2822 | 2474 | [WS_METHODS.pullRequestsRunAction]: (input) => |
| 2823 | | observeRpcEffect( |
| 2824 | | WS_METHODS.pullRequestsRunAction, |
| 2825 | | withPullRequestViewer(input, pullRequests.runAction(input)).pipe( |
| 2826 | | Effect.tap(() => |
| 2827 | | resolvePullRequestSyncKey(input).pipe( |
| 2828 | | Effect.flatMap((key) => |
| 2829 | | key === null ? Effect.void : pullRequestSync.requestSync(key), |
| 2830 | | ), |
| 2475 | withPullRequestViewer(input, pullRequests.runAction(input)).pipe( |
| 2476 | Effect.tap(() => |
| 2477 | resolvePullRequestSyncKey(input).pipe( |
| 2478 | Effect.flatMap((key) => |
| 2479 | key === null ? Effect.void : pullRequestSync.requestSync(key), |
| 2831 | 2480 | ), |
| 2832 | 2481 | ), |
| 2833 | 2482 | ), |
| 2834 | | { "rpc.aggregate": "pull-requests" }, |
| 2835 | 2483 | ), |
| 2836 | 2484 | [WS_METHODS.pullRequestsUpdate]: (input) => |
| 2837 | | observeRpcEffect( |
| 2838 | | WS_METHODS.pullRequestsUpdate, |
| 2839 | | withPullRequestViewer(input, pullRequests.update(input)), |
| 2840 | | { |
| 2841 | | "rpc.aggregate": "pull-requests", |
| 2842 | | }, |
| 2843 | | ), |
| 2485 | withPullRequestViewer(input, pullRequests.update(input)), |
| 2844 | 2486 | [WS_METHODS.pullRequestsComment]: (input) => |
| 2845 | | observeRpcEffect( |
| 2846 | | WS_METHODS.pullRequestsComment, |
| 2847 | | withPullRequestViewer(input, pullRequests.comment(input)), |
| 2848 | | { |
| 2849 | | "rpc.aggregate": "pull-requests", |
| 2850 | | }, |
| 2851 | | ), |
| 2487 | withPullRequestViewer(input, pullRequests.comment(input)), |
| 2852 | 2488 | [WS_METHODS.pullRequestsUpdateComment]: (input) => |
| 2853 | | observeRpcEffect( |
| 2854 | | WS_METHODS.pullRequestsUpdateComment, |
| 2855 | | withPullRequestViewer(input, pullRequests.updateComment(input)), |
| 2856 | | { |
| 2857 | | "rpc.aggregate": "pull-requests", |
| 2858 | | }, |
| 2859 | | ), |
| 2489 | withPullRequestViewer(input, pullRequests.updateComment(input)), |
| 2860 | 2490 | [WS_METHODS.pullRequestsSubmitReview]: (input) => |
| 2861 | | observeRpcEffect( |
| 2862 | | WS_METHODS.pullRequestsSubmitReview, |
| 2863 | | withPullRequestViewer(input, pullRequests.submitReview(input)), |
| 2864 | | { |
| 2865 | | "rpc.aggregate": "pull-requests", |
| 2866 | | }, |
| 2867 | | ), |
| 2491 | withPullRequestViewer(input, pullRequests.submitReview(input)), |
| 2868 | 2492 | [WS_METHODS.pullRequestsReplyToThread]: (input) => |
| 2869 | | observeRpcEffect( |
| 2870 | | WS_METHODS.pullRequestsReplyToThread, |
| 2871 | | withPullRequestViewer(input, pullRequests.replyToThread(input)), |
| 2872 | | { "rpc.aggregate": "pull-requests" }, |
| 2873 | | ), |
| 2493 | withPullRequestViewer(input, pullRequests.replyToThread(input)), |
| 2874 | 2494 | [WS_METHODS.pullRequestsSetThreadResolution]: (input) => |
| 2875 | | observeRpcEffect( |
| 2876 | | WS_METHODS.pullRequestsSetThreadResolution, |
| 2877 | | withPullRequestViewer(input, pullRequests.setThreadResolution(input)), |
| 2878 | | { "rpc.aggregate": "pull-requests" }, |
| 2879 | | ), |
| 2495 | withPullRequestViewer(input, pullRequests.setThreadResolution(input)), |
| 2880 | 2496 | [WS_METHODS.pullRequestsSetReaction]: (input) => |
| 2881 | | observeRpcEffect( |
| 2882 | | WS_METHODS.pullRequestsSetReaction, |
| 2883 | | withPullRequestViewer(input, pullRequests.setReaction(input)), |
| 2884 | | { |
| 2885 | | "rpc.aggregate": "pull-requests", |
| 2886 | | }, |
| 2887 | | ), |
| 2497 | withPullRequestViewer(input, pullRequests.setReaction(input)), |
| 2888 | 2498 | [WS_METHODS.pullRequestsInvalidate]: (input) => |
| 2889 | | observeRpcEffect( |
| 2890 | | WS_METHODS.pullRequestsInvalidate, |
| 2891 | | pullRequests.invalidate(input, { notifyReaders: true }).pipe( |
| 2892 | | // A reader asking for fresh host state also wants the thread badges it feeds to |
| 2893 | | // catch up, including a merged link the sweep would otherwise never revisit. |
| 2894 | | Effect.andThen( |
| 2895 | | input.reference === undefined || input.filesViewedOnly === true |
| 2896 | | ? Effect.void |
| 2897 | | : resolvePullRequestSyncKey(input.reference).pipe( |
| 2898 | | Effect.flatMap((key) => |
| 2899 | | key === null ? Effect.void : pullRequestSync.requestSync(key), |
| 2900 | | ), |
| 2499 | pullRequests.invalidate(input, { notifyReaders: true }).pipe( |
| 2500 | // A reader asking for fresh host state also wants the thread badges it feeds to |
| 2501 | // catch up, including a merged link the sweep would otherwise never revisit. |
| 2502 | Effect.andThen( |
| 2503 | input.reference === undefined || input.filesViewedOnly === true |
| 2504 | ? Effect.void |
| 2505 | : resolvePullRequestSyncKey(input.reference).pipe( |
| 2506 | Effect.flatMap((key) => |
| 2507 | key === null ? Effect.void : pullRequestSync.requestSync(key), |
| 2901 | 2508 | ), |
| 2902 | | ), |
| 2509 | ), |
| 2903 | 2510 | ), |
| 2904 | | { "rpc.aggregate": "pull-requests" }, |
| 2905 | | ), |
| 2906 | | [WS_METHODS.pullRequestsSubscribeRefreshes]: () => |
| 2907 | | observeRpcStream( |
| 2908 | | WS_METHODS.pullRequestsSubscribeRefreshes, |
| 2909 | | pullRequests.subscribeRefreshes, |
| 2910 | | { "rpc.aggregate": "pull-requests" }, |
| 2911 | 2511 | ), |
| 2512 | [WS_METHODS.pullRequestsSubscribeRefreshes]: () => pullRequests.subscribeRefreshes, |
| 2912 | 2513 | [WS_METHODS.pullRequestsReviewerCandidates]: (input) => |
| 2913 | | observeRpcEffect( |
| 2914 | | WS_METHODS.pullRequestsReviewerCandidates, |
| 2915 | | withPullRequestViewer(input, pullRequests.reviewerCandidates(input)), |
| 2916 | | { "rpc.aggregate": "pull-requests" }, |
| 2917 | | ), |
| 2514 | withPullRequestViewer(input, pullRequests.reviewerCandidates(input)), |
| 2918 | 2515 | [WS_METHODS.pullRequestsRequestReviewers]: (input) => |
| 2919 | | observeRpcEffect( |
| 2920 | | WS_METHODS.pullRequestsRequestReviewers, |
| 2921 | | withPullRequestViewer(input, pullRequests.requestReviewers(input)), |
| 2922 | | { "rpc.aggregate": "pull-requests" }, |
| 2923 | | ), |
| 2516 | withPullRequestViewer(input, pullRequests.requestReviewers(input)), |
| 2924 | 2517 | [WS_METHODS.pullRequestsLabelCandidates]: (input) => |
| 2925 | | observeRpcEffect( |
| 2926 | | WS_METHODS.pullRequestsLabelCandidates, |
| 2927 | | withPullRequestViewer(input, pullRequests.labelCandidates(input)), |
| 2928 | | { "rpc.aggregate": "pull-requests" }, |
| 2929 | | ), |
| 2518 | withPullRequestViewer(input, pullRequests.labelCandidates(input)), |
| 2930 | 2519 | [WS_METHODS.pullRequestsSetLabels]: (input) => |
| 2931 | | observeRpcEffect( |
| 2932 | | WS_METHODS.pullRequestsSetLabels, |
| 2933 | | withPullRequestViewer(input, pullRequests.setLabels(input)), |
| 2934 | | { |
| 2935 | | "rpc.aggregate": "pull-requests", |
| 2936 | | }, |
| 2937 | | ), |
| 2520 | withPullRequestViewer(input, pullRequests.setLabels(input)), |
| 2938 | 2521 | [WS_METHODS.sourceControlLookupRepository]: (input) => |
| 2939 | | observeRpcEffect( |
| 2940 | | WS_METHODS.sourceControlLookupRepository, |
| 2941 | | sourceControlRepositories.lookupRepository(input), |
| 2942 | | { |
| 2943 | | "rpc.aggregate": "source-control", |
| 2944 | | }, |
| 2945 | | ), |
| 2522 | sourceControlRepositories.lookupRepository(input), |
| 2946 | 2523 | [WS_METHODS.sourceControlCloneRepository]: (input) => |
| 2947 | | observeRpcEffect( |
| 2948 | | WS_METHODS.sourceControlCloneRepository, |
| 2949 | | sourceControlRepositories.cloneRepository(input), |
| 2950 | | { |
| 2951 | | "rpc.aggregate": "source-control", |
| 2952 | | }, |
| 2953 | | ), |
| 2524 | sourceControlRepositories.cloneRepository(input), |
| 2954 | 2525 | [WS_METHODS.projectCloneStart]: (input) => |
| 2955 | | observeRpcEffect( |
| 2956 | | WS_METHODS.projectCloneStart, |
| 2957 | | projectCloneTracker.start(input, { |
| 2958 | | createProject: (project) => |
| 2959 | | projectService |
| 2960 | | .create({ |
| 2961 | | commandId: CommandId.make(`project-clone-create:${project.projectId}`), |
| 2962 | | projectId: project.projectId, |
| 2963 | | title: project.title, |
| 2964 | | workspaceRoot: project.workspaceRoot, |
| 2965 | | createWorkspaceRootIfMissing: true, |
| 2966 | | }) |
| 2967 | | .pipe( |
| 2968 | | Effect.asVoid, |
| 2969 | | Effect.mapError( |
| 2970 | | (cause) => |
| 2971 | | new OrchestrationDispatchCommandError({ |
| 2972 | | message: "Failed to create clone project.", |
| 2973 | | cause, |
| 2974 | | }), |
| 2975 | | ), |
| 2976 | | ), |
| 2977 | | onCloned: (project) => |
| 2978 | | repositoryIdentityResolver.resolve(project.workspaceRoot, { refresh: true }).pipe( |
| 2979 | | Effect.andThen( |
| 2980 | | projectService.update({ |
| 2981 | | commandId: CommandId.make(`project-clone-done:${project.projectId}`), |
| 2982 | | projectId: project.projectId, |
| 2983 | | }), |
| 2526 | projectCloneTracker.start(input, { |
| 2527 | createProject: (project) => |
| 2528 | projectService |
| 2529 | .create({ |
| 2530 | commandId: CommandId.make(`project-clone-create:${project.projectId}`), |
| 2531 | projectId: project.projectId, |
| 2532 | title: project.title, |
| 2533 | workspaceRoot: project.workspaceRoot, |
| 2534 | createWorkspaceRootIfMissing: true, |
| 2535 | }) |
| 2536 | .pipe( |
| 2537 | Effect.asVoid, |
| 2538 | Effect.mapError( |
| 2539 | (cause) => |
| 2540 | new OrchestrationDispatchCommandError({ |
| 2541 | message: "Failed to create clone project.", |
| 2542 | cause, |
| 2543 | }), |
| 2984 | 2544 | ), |
| 2985 | | Effect.andThen(refreshGitStatus(project.workspaceRoot)), |
| 2986 | | Effect.ignoreCause({ log: true }), |
| 2987 | 2545 | ), |
| 2988 | | }), |
| 2989 | | { "rpc.aggregate": "source-control" }, |
| 2990 | | ), |
| 2991 | | [WS_METHODS.projectsEnsureScratch]: () => |
| 2992 | | observeRpcEffect( |
| 2993 | | WS_METHODS.projectsEnsureScratch, |
| 2994 | | managedFolders.ensureScratchProject.pipe( |
| 2995 | | Effect.mapError( |
| 2996 | | (cause) => new OrchestrationDispatchCommandError({ message: cause.message, cause }), |
| 2546 | onCloned: (project) => |
| 2547 | repositoryIdentityResolver.resolve(project.workspaceRoot, { refresh: true }).pipe( |
| 2548 | Effect.andThen( |
| 2549 | projectService.update({ |
| 2550 | commandId: CommandId.make(`project-clone-done:${project.projectId}`), |
| 2551 | projectId: project.projectId, |
| 2552 | }), |
| 2553 | ), |
| 2554 | Effect.andThen(refreshGitStatus(project.workspaceRoot)), |
| 2555 | Effect.ignoreCause({ log: true }), |
| 2997 | 2556 | ), |
| 2557 | }), |
| 2558 | [WS_METHODS.projectsEnsureScratch]: () => |
| 2559 | managedFolders.ensureScratchProject.pipe( |
| 2560 | Effect.mapError( |
| 2561 | (cause) => new OrchestrationDispatchCommandError({ message: cause.message, cause }), |
| 2998 | 2562 | ), |
| 2999 | | { "rpc.aggregate": "orchestration" }, |
| 3000 | 2563 | ), |
| 3001 | 2564 | [WS_METHODS.projectsCreateNew]: (input) => |
| 3002 | | observeRpcEffect( |
| 3003 | | WS_METHODS.projectsCreateNew, |
| 3004 | | managedFolders |
| 3005 | | .createNamedProject(input) |
| 3006 | | .pipe( |
| 3007 | | Effect.mapError( |
| 3008 | | (cause) => |
| 3009 | | new OrchestrationDispatchCommandError({ message: cause.message, cause }), |
| 3010 | | ), |
| 2565 | managedFolders |
| 2566 | .createNamedProject(input) |
| 2567 | .pipe( |
| 2568 | Effect.mapError( |
| 2569 | (cause) => new OrchestrationDispatchCommandError({ message: cause.message, cause }), |
| 3011 | 2570 | ), |
| 3012 | | { "rpc.aggregate": "orchestration" }, |
| 3013 | | ), |
| 2571 | ), |
| 3014 | 2572 | [WS_METHODS.projectCloneCancel]: (input) => |
| 3015 | | observeRpcEffect( |
| 3016 | | WS_METHODS.projectCloneCancel, |
| 3017 | | projectCloneTracker |
| 3018 | | .cancel(input.projectId) |
| 3019 | | .pipe(Effect.map((applied) => ({ applied }))), |
| 3020 | | { "rpc.aggregate": "source-control" }, |
| 3021 | | ), |
| 2573 | projectCloneTracker.cancel(input.projectId).pipe(Effect.map((applied) => ({ applied }))), |
| 3022 | 2574 | [WS_METHODS.projectCloneRetry]: (input) => |
| 3023 | | observeRpcEffect( |
| 3024 | | WS_METHODS.projectCloneRetry, |
| 3025 | | projectCloneTracker.retry(input.projectId).pipe(Effect.map((applied) => ({ applied }))), |
| 3026 | | { "rpc.aggregate": "source-control" }, |
| 3027 | | ), |
| 3028 | | [WS_METHODS.subscribeProjectClones]: () => |
| 3029 | | observeRpcStream(WS_METHODS.subscribeProjectClones, projectCloneTracker.stream, { |
| 3030 | | "rpc.aggregate": "source-control", |
| 3031 | | }), |
| 2575 | projectCloneTracker.retry(input.projectId).pipe(Effect.map((applied) => ({ applied }))), |
| 2576 | [WS_METHODS.subscribeProjectClones]: () => projectCloneTracker.stream, |
| 3032 | 2577 | [WS_METHODS.sourceControlPublishRepository]: (input) => |
| 3033 | | observeRpcEffect( |
| 3034 | | WS_METHODS.sourceControlPublishRepository, |
| 3035 | | sourceControlRepositories.publishRepository(input).pipe( |
| 3036 | | // A new remote can change the cached identity. Only the `cwd` entry |
| 3037 | | // refreshes, so after a publish from a linked worktree the project |
| 3038 | | // root entry waits for its TTL. |
| 3039 | | Effect.tap(() => repositoryIdentityResolver.resolve(input.cwd, { refresh: true })), |
| 3040 | | Effect.tap(() => refreshGitStatus(input.cwd)), |
| 3041 | | ), |
| 3042 | | { |
| 3043 | | "rpc.aggregate": "source-control", |
| 3044 | | }, |
| 2578 | sourceControlRepositories.publishRepository(input).pipe( |
| 2579 | // A new remote can change the cached identity. Only the `cwd` entry |
| 2580 | // refreshes, so after a publish from a linked worktree the project |
| 2581 | // root entry waits for its TTL. |
| 2582 | Effect.tap(() => repositoryIdentityResolver.resolve(input.cwd, { refresh: true })), |
| 2583 | Effect.tap(() => refreshGitStatus(input.cwd)), |
| 3045 | 2584 | ), |
| 3046 | 2585 | [WS_METHODS.projectsSearchEntries]: (input) => |
| 3047 | | observeRpcEffect( |
| 3048 | | WS_METHODS.projectsSearchEntries, |
| 3049 | | workspaceEntries.search(input).pipe( |
| 3050 | | Effect.mapError( |
| 3051 | | (cause) => |
| 3052 | | new ProjectSearchEntriesError({ |
| 3053 | | cwd: input.cwd, |
| 3054 | | queryLength: input.query.length, |
| 3055 | | limit: input.limit, |
| 3056 | | ...projectEntriesFailureContext(cause), |
| 3057 | | cause, |
| 3058 | | }), |
| 3059 | | ), |
| 2586 | workspaceEntries.search(input).pipe( |
| 2587 | Effect.mapError( |
| 2588 | (cause) => |
| 2589 | new ProjectSearchEntriesError({ |
| 2590 | cwd: input.cwd, |
| 2591 | queryLength: input.query.length, |
| 2592 | limit: input.limit, |
| 2593 | ...projectEntriesFailureContext(cause), |
| 2594 | cause, |
| 2595 | }), |
| 3060 | 2596 | ), |
| 3061 | | { "rpc.aggregate": "workspace" }, |
| 3062 | 2597 | ), |
| 3063 | 2598 | [WS_METHODS.projectsSearchContents]: (input) => |
| 3064 | | observeRpcEffect( |
| 3065 | | WS_METHODS.projectsSearchContents, |
| 3066 | | workspaceEntries.searchContents(input).pipe( |
| 3067 | | Effect.mapError( |
| 3068 | | (cause) => |
| 3069 | | new ProjectSearchContentsError({ |
| 3070 | | cwd: input.cwd, |
| 3071 | | queryLength: input.query.length, |
| 3072 | | limit: input.limit, |
| 3073 | | ...projectEntriesFailureContext(cause), |
| 3074 | | cause, |
| 3075 | | }), |
| 3076 | | ), |
| 2599 | workspaceEntries.searchContents(input).pipe( |
| 2600 | Effect.mapError( |
| 2601 | (cause) => |
| 2602 | new ProjectSearchContentsError({ |
| 2603 | cwd: input.cwd, |
| 2604 | queryLength: input.query.length, |
| 2605 | limit: input.limit, |
| 2606 | ...projectEntriesFailureContext(cause), |
| 2607 | cause, |
| 2608 | }), |
| 3077 | 2609 | ), |
| 3078 | | { "rpc.aggregate": "workspace" }, |
| 3079 | 2610 | ), |
| 3080 | 2611 | [WS_METHODS.projectsListEntries]: (input) => |
| 3081 | | observeRpcEffect( |
| 3082 | | WS_METHODS.projectsListEntries, |
| 3083 | | workspaceEntries.list(input).pipe( |
| 3084 | | Effect.mapError( |
| 3085 | | (cause) => |
| 3086 | | new ProjectListEntriesError({ |
| 3087 | | ...input, |
| 3088 | | ...projectEntriesFailureContext(cause), |
| 3089 | | cause, |
| 3090 | | }), |
| 3091 | | ), |
| 2612 | workspaceEntries.list(input).pipe( |
| 2613 | Effect.mapError( |
| 2614 | (cause) => |
| 2615 | new ProjectListEntriesError({ |
| 2616 | ...input, |
| 2617 | ...projectEntriesFailureContext(cause), |
| 2618 | cause, |
| 2619 | }), |
| 3092 | 2620 | ), |
| 3093 | | { "rpc.aggregate": "workspace" }, |
| 3094 | 2621 | ), |
| 3095 | 2622 | [WS_METHODS.projectsReadFile]: (input) => |
| 3096 | | observeRpcEffect( |
| 3097 | | WS_METHODS.projectsReadFile, |
| 3098 | | workspaceFileSystem.readFile(input).pipe( |
| 3099 | | Effect.mapError( |
| 3100 | | (cause) => |
| 3101 | | new ProjectReadFileError({ |
| 3102 | | ...input, |
| 3103 | | ...projectFileFailureContext(cause), |
| 3104 | | cause, |
| 3105 | | }), |
| 3106 | | ), |
| 2623 | workspaceFileSystem.readFile(input).pipe( |
| 2624 | Effect.mapError( |
| 2625 | (cause) => |
| 2626 | new ProjectReadFileError({ |
| 2627 | ...input, |
| 2628 | ...projectFileFailureContext(cause), |
| 2629 | cause, |
| 2630 | }), |
| 3107 | 2631 | ), |
| 3108 | | { "rpc.aggregate": "workspace" }, |
| 3109 | 2632 | ), |
| 3110 | 2633 | [WS_METHODS.projectsWriteFile]: (input) => |
| 3111 | | observeRpcEffect( |
| 3112 | | WS_METHODS.projectsWriteFile, |
| 3113 | | workspaceFileSystem.writeFile(input).pipe( |
| 3114 | | Effect.mapError( |
| 3115 | | (cause) => |
| 3116 | | new ProjectWriteFileError({ |
| 3117 | | cwd: input.cwd, |
| 3118 | | relativePath: input.relativePath, |
| 3119 | | ...projectFileFailureContext(cause), |
| 3120 | | cause, |
| 3121 | | }), |
| 3122 | | ), |
| 2634 | workspaceFileSystem.writeFile(input).pipe( |
| 2635 | Effect.mapError( |
| 2636 | (cause) => |
| 2637 | new ProjectWriteFileError({ |
| 2638 | cwd: input.cwd, |
| 2639 | relativePath: input.relativePath, |
| 2640 | ...projectFileFailureContext(cause), |
| 2641 | cause, |
| 2642 | }), |
| 3123 | 2643 | ), |
| 3124 | | { "rpc.aggregate": "workspace" }, |
| 3125 | 2644 | ), |
| 3126 | 2645 | [WS_METHODS.projectsMutate]: (mutation) => |
| 3127 | | observeRpcEffect( |
| 3128 | | WS_METHODS.projectsMutate, |
| 3129 | | startup.enqueueCommand(mutateProject(mutation)).pipe( |
| 3130 | | Effect.mapError( |
| 3131 | | (cause) => |
| 3132 | | new ProjectMutationError({ |
| 3133 | | commandId: mutation.commandId, |
| 3134 | | message: |
| 3135 | | cause._tag === "ProjectNotEmptyError" |
| 3136 | | ? cause.message |
| 3137 | | : "Failed to mutate project.", |
| 3138 | | cause, |
| 3139 | | }), |
| 3140 | | ), |
| 2646 | startup.enqueueCommand(mutateProject(mutation)).pipe( |
| 2647 | Effect.mapError( |
| 2648 | (cause) => |
| 2649 | new ProjectMutationError({ |
| 2650 | commandId: mutation.commandId, |
| 2651 | message: |
| 2652 | cause._tag === "ProjectNotEmptyError" |
| 2653 | ? cause.message |
| 2654 | : "Failed to mutate project.", |
| 2655 | cause, |
| 2656 | }), |
| 3141 | 2657 | ), |
| 3142 | | { "rpc.aggregate": "orchestration" }, |
| 3143 | 2658 | ), |
| 3144 | | [WS_METHODS.shellOpenInEditor]: (input) => |
| 3145 | | observeRpcEffect(WS_METHODS.shellOpenInEditor, externalLauncher.launchEditor(input), { |
| 3146 | | "rpc.aggregate": "workspace", |
| 3147 | | }), |
| 2659 | [WS_METHODS.shellOpenInEditor]: (input) => externalLauncher.launchEditor(input), |
| 3148 | 2660 | [WS_METHODS.filesystemBrowse]: (input) => |
| 3149 | | observeRpcEffect( |
| 3150 | | WS_METHODS.filesystemBrowse, |
| 3151 | | workspaceEntries.browse(input).pipe( |
| 3152 | | Effect.mapError( |
| 3153 | | (cause) => |
| 3154 | | new FilesystemBrowseError({ |
| 3155 | | ...input, |
| 3156 | | ...filesystemBrowseFailureContext(cause), |
| 3157 | | cause, |
| 3158 | | }), |
| 3159 | | ), |
| 2661 | workspaceEntries.browse(input).pipe( |
| 2662 | Effect.mapError( |
| 2663 | (cause) => |
| 2664 | new FilesystemBrowseError({ |
| 2665 | ...input, |
| 2666 | ...filesystemBrowseFailureContext(cause), |
| 2667 | cause, |
| 2668 | }), |
| 3160 | 2669 | ), |
| 3161 | | { "rpc.aggregate": "workspace" }, |
| 3162 | 2670 | ), |
| 3163 | | [WS_METHODS.attachmentsCreateUploadUrl]: (input) => |
| 3164 | | observeRpcEffect(WS_METHODS.attachmentsCreateUploadUrl, issueAttachmentUploadUrl(input), { |
| 3165 | | "rpc.aggregate": "workspace", |
| 3166 | | }), |
| 3167 | | [WS_METHODS.attachmentsDelete]: (input) => |
| 3168 | | observeRpcEffect( |
| 3169 | | WS_METHODS.attachmentsDelete, |
| 3170 | | deletePendingAttachment(input.attachmentId), |
| 3171 | | { "rpc.aggregate": "workspace" }, |
| 3172 | | ), |
| 3173 | | [WS_METHODS.agentSessionsScan]: () => |
| 3174 | | observeRpcEffect(WS_METHODS.agentSessionsScan, agentSessionScanner.scan, { |
| 3175 | | "rpc.aggregate": "workspace", |
| 3176 | | }), |
| 2671 | [WS_METHODS.attachmentsCreateUploadUrl]: (input) => issueAttachmentUploadUrl(input), |
| 2672 | [WS_METHODS.attachmentsDelete]: (input) => deletePendingAttachment(input.attachmentId), |
| 2673 | [WS_METHODS.agentSessionsScan]: () => agentSessionScanner.scan, |
| 3177 | 2674 | [WS_METHODS.agentSessionsImport]: (input) => |
| 3178 | | observeRpcEffect( |
| 3179 | | WS_METHODS.agentSessionsImport, |
| 3180 | | agentSessionImporter.importRecentAgentThreads(input), |
| 3181 | | { "rpc.aggregate": "workspace" }, |
| 3182 | | ), |
| 2675 | agentSessionImporter.importRecentAgentThreads(input), |
| 3183 | 2676 | [WS_METHODS.assetsCreateUrl]: (input) => |
| 3184 | | observeRpcEffect( |
| 3185 | | WS_METHODS.assetsCreateUrl, |
| 3186 | | Effect.gen(function* () { |
| 3187 | | const path = yield* Path.Path; |
| 3188 | | // An absolute media path can be linked from a thread on another environment. |
| 3189 | | if ( |
| 3190 | | input.resource._tag === "attachment" || |
| 3191 | | input.resource._tag === "native-app-icon" || |
| 3192 | | input.resource._tag === "tool-output-image" || |
| 3193 | | // GitHub media names the repository it authenticates through itself. |
| 3194 | | input.resource._tag === "github-media" || |
| 3195 | | (input.resource._tag === "media-file" && path.isAbsolute(input.resource.path)) |
| 3196 | | ) { |
| 3197 | | return yield* issueAssetUrl({ resource: input.resource }); |
| 3198 | | } |
| 3199 | | if (input.resource._tag === "draft-workspace-file") { |
| 3200 | | // A project draft names its workspace directly; there is no |
| 3201 | | // thread to resolve one from. |
| 3202 | | return yield* issueAssetUrl({ |
| 3203 | | resource: input.resource, |
| 3204 | | workspaceRoot: input.resource.cwd, |
| 3205 | | }); |
| 3206 | | } |
| 3207 | | if (input.resource._tag === "project-favicon") { |
| 3208 | | const project = yield* projectStore |
| 3209 | | .findActiveByWorkspaceRoot(input.resource.cwd) |
| 3210 | | .pipe( |
| 3211 | | Effect.mapError( |
| 3212 | | (cause) => |
| 3213 | | new AssetWorkspaceContextResolutionError({ |
| 3214 | | resource: input.resource, |
| 3215 | | cause, |
| 3216 | | }), |
| 3217 | | ), |
| 3218 | | ); |
| 3219 | | if (Option.isNone(project)) { |
| 3220 | | return yield* new AssetWorkspaceContextNotFoundError({ |
| 3221 | | resource: input.resource, |
| 3222 | | }); |
| 3223 | | } |
| 3224 | | // A cloned project exists before its files do. Clients ask again |
| 3225 | | // when the clone lands (see createProjectFaviconUrlAtomFamily). |
| 3226 | | const clone = yield* projectCloneTracker.get(project.value.projectId); |
| 3227 | | return yield* issueAssetUrl({ |
| 3228 | | resource: input.resource, |
| 3229 | | ...(project.value.faviconPath |
| 3230 | | ? { projectFaviconPath: project.value.faviconPath } |
| 3231 | | : {}), |
| 3232 | | projectCheckoutPending: |
| 3233 | | clone !== null && |
| 3234 | | clone.phase !== "done" && |
| 3235 | | clone.destinationPath === project.value.workspaceRoot, |
| 3236 | | }); |
| 3237 | | } |
| 3238 | | const thread = yield* threadManagement |
| 3239 | | .getThreadRecords(input.resource.threadId, []) |
| 2677 | Effect.gen(function* () { |
| 2678 | const path = yield* Path.Path; |
| 2679 | // An absolute media path can be linked from a thread on another environment. |
| 2680 | if ( |
| 2681 | input.resource._tag === "attachment" || |
| 2682 | input.resource._tag === "native-app-icon" || |
| 2683 | input.resource._tag === "tool-output-image" || |
| 2684 | // GitHub media names the repository it authenticates through itself. |
| 2685 | input.resource._tag === "github-media" || |
| 2686 | (input.resource._tag === "media-file" && path.isAbsolute(input.resource.path)) |
| 2687 | ) { |
| 2688 | return yield* issueAssetUrl({ resource: input.resource }); |
| 2689 | } |
| 2690 | if (input.resource._tag === "draft-workspace-file") { |
| 2691 | // A project draft names its workspace directly; there is no |
| 2692 | // thread to resolve one from. |
| 2693 | return yield* issueAssetUrl({ |
| 2694 | resource: input.resource, |
| 2695 | workspaceRoot: input.resource.cwd, |
| 2696 | }); |
| 2697 | } |
| 2698 | if (input.resource._tag === "project-favicon") { |
| 2699 | const project = yield* projectStore |
| 2700 | .findActiveByWorkspaceRoot(input.resource.cwd) |
| 3240 | 2701 | .pipe( |
| 3241 | 2702 | Effect.mapError( |
| 3242 | 2703 | (cause) => |
| ... | ... | @@ -3246,7 +2707,28 @@ const layerWsRpc = ( |
| 3246 | 2707 | }), |
| 3247 | 2708 | ), |
| 3248 | 2709 | ); |
| 3249 | | const project = yield* projectService.getById(thread.thread.projectId).pipe( |
| 2710 | if (Option.isNone(project)) { |
| 2711 | return yield* new AssetWorkspaceContextNotFoundError({ |
| 2712 | resource: input.resource, |
| 2713 | }); |
| 2714 | } |
| 2715 | // A cloned project exists before its files do. Clients ask again |
| 2716 | // when the clone lands (see createProjectFaviconUrlAtomFamily). |
| 2717 | const clone = yield* projectCloneTracker.get(project.value.projectId); |
| 2718 | return yield* issueAssetUrl({ |
| 2719 | resource: input.resource, |
| 2720 | ...(project.value.faviconPath |
| 2721 | ? { projectFaviconPath: project.value.faviconPath } |
| 2722 | : {}), |
| 2723 | projectCheckoutPending: |
| 2724 | clone !== null && |
| 2725 | clone.phase !== "done" && |
| 2726 | clone.destinationPath === project.value.workspaceRoot, |
| 2727 | }); |
| 2728 | } |
| 2729 | const thread = yield* threadManagement |
| 2730 | .getThreadRecords(input.resource.threadId, []) |
| 2731 | .pipe( |
| 3250 | 2732 | Effect.mapError( |
| 3251 | 2733 | (cause) => |
| 3252 | 2734 | new AssetWorkspaceContextResolutionError({ |
| ... | ... | @@ -3255,357 +2737,187 @@ const layerWsRpc = ( |
| 3255 | 2737 | }), |
| 3256 | 2738 | ), |
| 3257 | 2739 | ); |
| 3258 | | if (Option.isNone(project)) { |
| 3259 | | return yield* new AssetWorkspaceContextNotFoundError({ |
| 3260 | | resource: input.resource, |
| 3261 | | }); |
| 3262 | | } |
| 3263 | | return yield* issueAssetUrl({ |
| 2740 | const project = yield* projectService.getById(thread.thread.projectId).pipe( |
| 2741 | Effect.mapError( |
| 2742 | (cause) => |
| 2743 | new AssetWorkspaceContextResolutionError({ |
| 2744 | resource: input.resource, |
| 2745 | cause, |
| 2746 | }), |
| 2747 | ), |
| 2748 | ); |
| 2749 | if (Option.isNone(project)) { |
| 2750 | return yield* new AssetWorkspaceContextNotFoundError({ |
| 3264 | 2751 | resource: input.resource, |
| 3265 | | workspaceRoot: thread.thread.worktreePath ?? project.value.workspaceRoot, |
| 3266 | 2752 | }); |
| 3267 | | }), |
| 3268 | | { "rpc.aggregate": "workspace" }, |
| 3269 | | ), |
| 2753 | } |
| 2754 | return yield* issueAssetUrl({ |
| 2755 | resource: input.resource, |
| 2756 | workspaceRoot: thread.thread.worktreePath ?? project.value.workspaceRoot, |
| 2757 | }); |
| 2758 | }), |
| 3270 | 2759 | [WS_METHODS.assetsPersistChatAttachments]: (input) => |
| 3271 | | observeRpcEffect( |
| 3272 | | WS_METHODS.assetsPersistChatAttachments, |
| 3273 | | persistChatAttachments(input).pipe(Effect.map((attachments) => ({ attachments }))), |
| 3274 | | { "rpc.aggregate": "orchestration" }, |
| 3275 | | ), |
| 2760 | persistChatAttachments(input).pipe(Effect.map((attachments) => ({ attachments }))), |
| 3276 | 2761 | [WS_METHODS.subscribeVcsStatus]: (input) => |
| 3277 | | observeRpcStream( |
| 3278 | | WS_METHODS.subscribeVcsStatus, |
| 3279 | | vcsStatusBroadcaster.streamStatus(input, { |
| 3280 | | automaticRemoteRefreshInterval: automaticGitFetchInterval, |
| 3281 | | }), |
| 3282 | | { |
| 3283 | | "rpc.aggregate": "vcs", |
| 3284 | | }, |
| 3285 | | ), |
| 3286 | | [WS_METHODS.subscribeWorktreeSetup]: (input) => |
| 3287 | | observeRpcStream( |
| 3288 | | WS_METHODS.subscribeWorktreeSetup, |
| 3289 | | worktreeSetupTracker.stream(input.threadId), |
| 3290 | | { "rpc.aggregate": "vcs" }, |
| 3291 | | ), |
| 2762 | vcsStatusBroadcaster.streamStatus(input, { |
| 2763 | automaticRemoteRefreshInterval: automaticGitFetchInterval, |
| 2764 | }), |
| 2765 | [WS_METHODS.subscribeWorktreeSetup]: (input) => worktreeSetupTracker.stream(input.threadId), |
| 3292 | 2766 | [WS_METHODS.worktreeSetupCancel]: (input) => |
| 3293 | | observeRpcEffect( |
| 3294 | | WS_METHODS.worktreeSetupCancel, |
| 3295 | | worktreeSetupTracker |
| 3296 | | .cancel(input.threadId) |
| 3297 | | .pipe(Effect.map((cancelled) => ({ cancelled }))), |
| 3298 | | { "rpc.aggregate": "vcs" }, |
| 3299 | | ), |
| 3300 | | [WS_METHODS.vcsRefreshStatus]: (input) => |
| 3301 | | observeRpcEffect( |
| 3302 | | WS_METHODS.vcsRefreshStatus, |
| 3303 | | vcsStatusBroadcaster.refreshStatus(input.cwd), |
| 3304 | | { |
| 3305 | | "rpc.aggregate": "vcs", |
| 3306 | | }, |
| 3307 | | ), |
| 2767 | worktreeSetupTracker |
| 2768 | .cancel(input.threadId) |
| 2769 | .pipe(Effect.map((cancelled) => ({ cancelled }))), |
| 2770 | [WS_METHODS.vcsRefreshStatus]: (input) => vcsStatusBroadcaster.refreshStatus(input.cwd), |
| 3308 | 2771 | [WS_METHODS.vcsPull]: (input) => |
| 3309 | | observeRpcEffect( |
| 3310 | | WS_METHODS.vcsPull, |
| 3311 | | gitWorkflow.pullCurrentBranch(input.cwd).pipe( |
| 3312 | | Effect.matchCauseEffect({ |
| 3313 | | onFailure: (cause) => Effect.failCause(cause), |
| 3314 | | onSuccess: (result) => |
| 3315 | | refreshGitStatus(input.cwd).pipe(Effect.ignore({ log: true }), Effect.as(result)), |
| 3316 | | }), |
| 3317 | | ), |
| 3318 | | { "rpc.aggregate": "git" }, |
| 2772 | gitWorkflow.pullCurrentBranch(input.cwd).pipe( |
| 2773 | Effect.matchCauseEffect({ |
| 2774 | onFailure: (cause) => Effect.failCause(cause), |
| 2775 | onSuccess: (result) => |
| 2776 | refreshGitStatus(input.cwd).pipe(Effect.ignore({ log: true }), Effect.as(result)), |
| 2777 | }), |
| 3319 | 2778 | ), |
| 3320 | 2779 | [WS_METHODS.gitRunStackedAction]: (input) => |
| 3321 | | observeRpcStream( |
| 3322 | | WS_METHODS.gitRunStackedAction, |
| 3323 | | Stream.callback<GitActionProgressEvent, GitManagerServiceError>((queue) => |
| 3324 | | gitWorkflow |
| 3325 | | .runStackedAction(input, { |
| 3326 | | actionId: input.actionId, |
| 3327 | | progressReporter: { |
| 3328 | | publish: (event) => Queue.offer(queue, event).pipe(Effect.asVoid), |
| 3329 | | }, |
| 3330 | | }) |
| 3331 | | .pipe( |
| 3332 | | Effect.matchCauseEffect({ |
| 3333 | | onFailure: (cause) => Queue.failCause(queue, cause), |
| 3334 | | onSuccess: (result) => |
| 3335 | | (input.threadId === undefined |
| 3336 | | ? Effect.void |
| 3337 | | : linkCreatedPullRequest({ |
| 3338 | | threadId: input.threadId, |
| 3339 | | result, |
| 3340 | | commandId: serverCommandId("pr-created-link"), |
| 3341 | | }).pipe( |
| 3342 | | Effect.provideService(Orchestrator.OrchestratorV2, orchestrationEngine), |
| 3343 | | Effect.provideService(ProjectService.ProjectService, projectService), |
| 3344 | | ) |
| 3345 | | ).pipe( |
| 3346 | | Effect.andThen( |
| 3347 | | refreshPushedPullRequests(input, result).pipe( |
| 3348 | | Effect.provideService(Orchestrator.OrchestratorV2, orchestrationEngine), |
| 3349 | | Effect.provideService(ProjectStore.ProjectStoreV2, projectStore), |
| 3350 | | Effect.provideService( |
| 3351 | | PullRequestService.PullRequestService, |
| 3352 | | pullRequests, |
| 3353 | | ), |
| 2780 | Stream.callback<GitActionProgressEvent, GitManagerServiceError>((queue) => |
| 2781 | gitWorkflow |
| 2782 | .runStackedAction(input, { |
| 2783 | actionId: input.actionId, |
| 2784 | progressReporter: { |
| 2785 | publish: (event) => Queue.offer(queue, event).pipe(Effect.asVoid), |
| 2786 | }, |
| 2787 | }) |
| 2788 | .pipe( |
| 2789 | Effect.matchCauseEffect({ |
| 2790 | onFailure: (cause) => Queue.failCause(queue, cause), |
| 2791 | onSuccess: (result) => |
| 2792 | (input.threadId === undefined |
| 2793 | ? Effect.void |
| 2794 | : linkCreatedPullRequest({ |
| 2795 | threadId: input.threadId, |
| 2796 | result, |
| 2797 | commandId: serverCommandId("pr-created-link"), |
| 2798 | }).pipe( |
| 2799 | Effect.provideService(Orchestrator.OrchestratorV2, orchestrationEngine), |
| 2800 | Effect.provideService(ProjectService.ProjectService, projectService), |
| 2801 | ) |
| 2802 | ).pipe( |
| 2803 | Effect.andThen( |
| 2804 | refreshPushedPullRequests(input, result).pipe( |
| 2805 | Effect.provideService(Orchestrator.OrchestratorV2, orchestrationEngine), |
| 2806 | Effect.provideService(ProjectStore.ProjectStoreV2, projectStore), |
| 2807 | Effect.provideService( |
| 2808 | PullRequestService.PullRequestService, |
| 2809 | pullRequests, |
| 3354 | 2810 | ), |
| 3355 | 2811 | ), |
| 3356 | | Effect.andThen(refreshGitStatus(input.cwd)), |
| 3357 | | Effect.andThen(Queue.end(queue).pipe(Effect.asVoid)), |
| 3358 | 2812 | ), |
| 3359 | | }), |
| 3360 | | ), |
| 3361 | | ), |
| 3362 | | { "rpc.aggregate": "vcs" }, |
| 3363 | | ), |
| 3364 | | [WS_METHODS.gitResolvePullRequest]: (input) => |
| 3365 | | observeRpcEffect( |
| 3366 | | WS_METHODS.gitResolvePullRequest, |
| 3367 | | gitWorkflow.resolvePullRequest(input), |
| 3368 | | { |
| 3369 | | "rpc.aggregate": "git", |
| 3370 | | }, |
| 2813 | Effect.andThen(refreshGitStatus(input.cwd)), |
| 2814 | Effect.andThen(Queue.end(queue).pipe(Effect.asVoid)), |
| 2815 | ), |
| 2816 | }), |
| 2817 | ), |
| 3371 | 2818 | ), |
| 2819 | [WS_METHODS.gitResolvePullRequest]: (input) => gitWorkflow.resolvePullRequest(input), |
| 3372 | 2820 | [WS_METHODS.gitPreparePullRequestThread]: (input) => |
| 3373 | | observeRpcEffect( |
| 3374 | | WS_METHODS.gitPreparePullRequestThread, |
| 3375 | | gitWorkflow |
| 3376 | | .preparePullRequestThread(input) |
| 3377 | | .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3378 | | { "rpc.aggregate": "git" }, |
| 3379 | | ), |
| 3380 | | [WS_METHODS.vcsListRefs]: (input) => |
| 3381 | | observeRpcEffect(WS_METHODS.vcsListRefs, gitWorkflow.listRefs(input), { |
| 3382 | | "rpc.aggregate": "vcs", |
| 3383 | | }), |
| 2821 | gitWorkflow |
| 2822 | .preparePullRequestThread(input) |
| 2823 | .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 2824 | [WS_METHODS.vcsListRefs]: (input) => gitWorkflow.listRefs(input), |
| 3384 | 2825 | [WS_METHODS.vcsCreateWorktree]: (input) => |
| 3385 | | observeRpcEffect( |
| 3386 | | WS_METHODS.vcsCreateWorktree, |
| 3387 | | gitWorkflow.createWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3388 | | { "rpc.aggregate": "vcs" }, |
| 3389 | | ), |
| 2826 | gitWorkflow.createWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3390 | 2827 | [WS_METHODS.vcsRemoveWorktree]: (input) => |
| 3391 | | observeRpcEffect( |
| 3392 | | WS_METHODS.vcsRemoveWorktree, |
| 3393 | | gitWorkflow.removeWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3394 | | { "rpc.aggregate": "vcs" }, |
| 3395 | | ), |
| 2828 | gitWorkflow.removeWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3396 | 2829 | [WS_METHODS.vcsCreateRef]: (input) => |
| 3397 | | observeRpcEffect( |
| 3398 | | WS_METHODS.vcsCreateRef, |
| 3399 | | gitWorkflow.createRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3400 | | { "rpc.aggregate": "vcs" }, |
| 3401 | | ), |
| 2830 | gitWorkflow.createRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3402 | 2831 | [WS_METHODS.vcsSwitchRef]: (input) => |
| 3403 | | observeRpcEffect( |
| 3404 | | WS_METHODS.vcsSwitchRef, |
| 3405 | | gitWorkflow.switchRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3406 | | { "rpc.aggregate": "vcs" }, |
| 3407 | | ), |
| 2832 | gitWorkflow.switchRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3408 | 2833 | [WS_METHODS.vcsInit]: (input) => |
| 3409 | | observeRpcEffect( |
| 3410 | | WS_METHODS.vcsInit, |
| 3411 | | vcsProvisioning |
| 3412 | | .initRepository(input) |
| 3413 | | .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 3414 | | { "rpc.aggregate": "vcs" }, |
| 3415 | | ), |
| 3416 | | [WS_METHODS.reviewGetDiffPreview]: (input) => |
| 3417 | | observeRpcEffect(WS_METHODS.reviewGetDiffPreview, review.getDiffPreview(input), { |
| 3418 | | "rpc.aggregate": "review", |
| 3419 | | }), |
| 3420 | | [WS_METHODS.reviewGetDiffFileContents]: (input) => |
| 3421 | | observeRpcEffect( |
| 3422 | | WS_METHODS.reviewGetDiffFileContents, |
| 3423 | | review.getDiffFileContents(input), |
| 3424 | | { "rpc.aggregate": "review" }, |
| 3425 | | ), |
| 3426 | | [WS_METHODS.terminalOpen]: (input) => |
| 3427 | | observeRpcEffect(WS_METHODS.terminalOpen, terminalManager.open(input), { |
| 3428 | | "rpc.aggregate": "terminal", |
| 3429 | | }), |
| 2834 | vcsProvisioning.initRepository(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), |
| 2835 | [WS_METHODS.reviewGetDiffPreview]: (input) => review.getDiffPreview(input), |
| 2836 | [WS_METHODS.reviewGetDiffFileContents]: (input) => review.getDiffFileContents(input), |
| 2837 | [WS_METHODS.terminalOpen]: (input) => terminalManager.open(input), |
| 3430 | 2838 | [WS_METHODS.terminalAttach]: (input) => |
| 3431 | | observeRpcStream( |
| 3432 | | WS_METHODS.terminalAttach, |
| 3433 | | Stream.callback<TerminalAttachStreamEvent, TerminalError>((queue) => |
| 3434 | | Effect.acquireRelease( |
| 3435 | | terminalManager.attachStream(input, (event) => Queue.offer(queue, event)), |
| 3436 | | (unsubscribe) => Effect.sync(unsubscribe), |
| 3437 | | ), |
| 2839 | Stream.callback<TerminalAttachStreamEvent, TerminalError>((queue) => |
| 2840 | Effect.acquireRelease( |
| 2841 | terminalManager.attachStream(input, (event) => Queue.offer(queue, event)), |
| 2842 | (unsubscribe) => Effect.sync(unsubscribe), |
| 3438 | 2843 | ), |
| 3439 | | { "rpc.aggregate": "terminal" }, |
| 3440 | 2844 | ), |
| 3441 | | [WS_METHODS.terminalWrite]: (input) => |
| 3442 | | observeRpcEffect(WS_METHODS.terminalWrite, terminalManager.write(input), { |
| 3443 | | "rpc.aggregate": "terminal", |
| 3444 | | }), |
| 3445 | | [WS_METHODS.terminalResize]: (input) => |
| 3446 | | observeRpcEffect(WS_METHODS.terminalResize, terminalManager.resize(input), { |
| 3447 | | "rpc.aggregate": "terminal", |
| 3448 | | }), |
| 3449 | | [WS_METHODS.terminalClear]: (input) => |
| 3450 | | observeRpcEffect(WS_METHODS.terminalClear, terminalManager.clear(input), { |
| 3451 | | "rpc.aggregate": "terminal", |
| 3452 | | }), |
| 3453 | | [WS_METHODS.terminalRestart]: (input) => |
| 3454 | | observeRpcEffect(WS_METHODS.terminalRestart, terminalManager.restart(input), { |
| 3455 | | "rpc.aggregate": "terminal", |
| 3456 | | }), |
| 3457 | | [WS_METHODS.terminalClose]: (input) => |
| 3458 | | observeRpcEffect(WS_METHODS.terminalClose, terminalManager.close(input), { |
| 3459 | | "rpc.aggregate": "terminal", |
| 3460 | | }), |
| 2845 | [WS_METHODS.terminalWrite]: (input) => terminalManager.write(input), |
| 2846 | [WS_METHODS.terminalResize]: (input) => terminalManager.resize(input), |
| 2847 | [WS_METHODS.terminalClear]: (input) => terminalManager.clear(input), |
| 2848 | [WS_METHODS.terminalRestart]: (input) => terminalManager.restart(input), |
| 2849 | [WS_METHODS.terminalClose]: (input) => terminalManager.close(input), |
| 3461 | 2850 | [WS_METHODS.subscribeTerminalEvents]: (_input) => |
| 3462 | | observeRpcStream( |
| 3463 | | WS_METHODS.subscribeTerminalEvents, |
| 3464 | | Stream.callback<TerminalEvent>((queue) => |
| 3465 | | Effect.acquireRelease( |
| 3466 | | terminalManager.subscribe((event) => Queue.offer(queue, event)), |
| 3467 | | (unsubscribe) => Effect.sync(unsubscribe), |
| 3468 | | ), |
| 2851 | Stream.callback<TerminalEvent>((queue) => |
| 2852 | Effect.acquireRelease( |
| 2853 | terminalManager.subscribe((event) => Queue.offer(queue, event)), |
| 2854 | (unsubscribe) => Effect.sync(unsubscribe), |
| 3469 | 2855 | ), |
| 3470 | | { "rpc.aggregate": "terminal" }, |
| 3471 | 2856 | ), |
| 3472 | 2857 | [WS_METHODS.subscribeTerminalMetadata]: (_input) => |
| 3473 | | observeRpcStream( |
| 3474 | | WS_METHODS.subscribeTerminalMetadata, |
| 3475 | | Stream.callback<TerminalMetadataStreamEvent>((queue) => |
| 3476 | | Effect.acquireRelease( |
| 3477 | | terminalManager.subscribeMetadata((event) => Queue.offer(queue, event)), |
| 3478 | | (unsubscribe) => Effect.sync(unsubscribe), |
| 3479 | | ), |
| 2858 | Stream.callback<TerminalMetadataStreamEvent>((queue) => |
| 2859 | Effect.acquireRelease( |
| 2860 | terminalManager.subscribeMetadata((event) => Queue.offer(queue, event)), |
| 2861 | (unsubscribe) => Effect.sync(unsubscribe), |
| 3480 | 2862 | ), |
| 3481 | | { "rpc.aggregate": "terminal" }, |
| 3482 | 2863 | ), |
| 3483 | | [WS_METHODS.previewOpen]: (input) => |
| 3484 | | observeRpcEffect(WS_METHODS.previewOpen, previewManager.open(input), { |
| 3485 | | "rpc.aggregate": "preview", |
| 3486 | | }), |
| 3487 | | [WS_METHODS.previewNavigate]: (input) => |
| 3488 | | observeRpcEffect(WS_METHODS.previewNavigate, previewManager.navigate(input), { |
| 3489 | | "rpc.aggregate": "preview", |
| 3490 | | }), |
| 3491 | | [WS_METHODS.previewResize]: (input) => |
| 3492 | | observeRpcEffect(WS_METHODS.previewResize, previewManager.resize(input), { |
| 3493 | | "rpc.aggregate": "preview", |
| 3494 | | }), |
| 3495 | | [WS_METHODS.previewAdjust]: (input) => |
| 3496 | | observeRpcEffect(WS_METHODS.previewAdjust, previewManager.adjust(input), { |
| 3497 | | "rpc.aggregate": "preview", |
| 3498 | | }), |
| 3499 | | [WS_METHODS.previewRefresh]: (input) => |
| 3500 | | observeRpcEffect(WS_METHODS.previewRefresh, previewManager.refresh(input), { |
| 3501 | | "rpc.aggregate": "preview", |
| 3502 | | }), |
| 3503 | | [WS_METHODS.previewClose]: (input) => |
| 3504 | | observeRpcEffect(WS_METHODS.previewClose, previewManager.close(input), { |
| 3505 | | "rpc.aggregate": "preview", |
| 3506 | | }), |
| 3507 | | [WS_METHODS.previewList]: (input) => |
| 3508 | | observeRpcEffect(WS_METHODS.previewList, previewManager.list(input), { |
| 3509 | | "rpc.aggregate": "preview", |
| 3510 | | }), |
| 3511 | | [WS_METHODS.previewClearProfile]: (input) => |
| 3512 | | observeRpcEffect( |
| 3513 | | WS_METHODS.previewClearProfile, |
| 3514 | | serverBrowser.clearProfile(input.profileId), |
| 3515 | | { "rpc.aggregate": "preview" }, |
| 3516 | | ), |
| 3517 | | [WS_METHODS.previewReportStatus]: (input) => |
| 3518 | | observeRpcEffect(WS_METHODS.previewReportStatus, previewManager.reportStatus(input), { |
| 3519 | | "rpc.aggregate": "preview", |
| 3520 | | }), |
| 3521 | | [WS_METHODS.subscribePreviewEvents]: (_input) => |
| 3522 | | observeRpcStream(WS_METHODS.subscribePreviewEvents, previewManager.events, { |
| 3523 | | "rpc.aggregate": "preview", |
| 3524 | | }), |
| 3525 | | [WS_METHODS.deviceConfigure]: (input) => |
| 3526 | | observeRpcEffect(WS_METHODS.deviceConfigure, deviceService.configure(input), { |
| 3527 | | "rpc.aggregate": "device", |
| 3528 | | }), |
| 3529 | | [WS_METHODS.deviceTestHost]: (input) => |
| 3530 | | observeRpcEffect(WS_METHODS.deviceTestHost, deviceService.testHost(input), { |
| 3531 | | "rpc.aggregate": "device", |
| 3532 | | }), |
| 2864 | [WS_METHODS.previewOpen]: (input) => previewManager.open(input), |
| 2865 | [WS_METHODS.previewNavigate]: (input) => previewManager.navigate(input), |
| 2866 | [WS_METHODS.previewResize]: (input) => previewManager.resize(input), |
| 2867 | [WS_METHODS.previewAdjust]: (input) => previewManager.adjust(input), |
| 2868 | [WS_METHODS.previewRefresh]: (input) => previewManager.refresh(input), |
| 2869 | [WS_METHODS.previewClose]: (input) => previewManager.close(input), |
| 2870 | [WS_METHODS.previewList]: (input) => previewManager.list(input), |
| 2871 | [WS_METHODS.previewClearProfile]: (input) => serverBrowser.clearProfile(input.profileId), |
| 2872 | [WS_METHODS.previewReportStatus]: (input) => previewManager.reportStatus(input), |
| 2873 | [WS_METHODS.subscribePreviewEvents]: (_input) => previewManager.events, |
| 2874 | [WS_METHODS.deviceConfigure]: (input) => deviceService.configure(input), |
| 2875 | [WS_METHODS.deviceTestHost]: (input) => deviceService.testHost(input), |
| 3533 | 2876 | [WS_METHODS.deviceList]: (input) => |
| 3534 | | observeRpcEffect( |
| 3535 | | WS_METHODS.deviceList, |
| 3536 | | input.inspectOnly && !input.updateTool |
| 3537 | | ? deviceService.inspect |
| 3538 | | : authorizeEffect( |
| 3539 | | requiredScopeForDeviceList(input), |
| 3540 | | input.updateTool |
| 3541 | | ? deviceService.updateTool(input.updateTool) |
| 3542 | | : input.retryHostId |
| 3543 | | ? deviceService.retryHost(input.retryHostId) |
| 3544 | | : deviceService.list, |
| 3545 | | ), |
| 3546 | | { |
| 3547 | | "rpc.aggregate": "device", |
| 3548 | | }, |
| 3549 | | ), |
| 3550 | | [WS_METHODS.deviceOpen]: (input) => |
| 3551 | | observeRpcEffect(WS_METHODS.deviceOpen, deviceService.open(input), { |
| 3552 | | "rpc.aggregate": "device", |
| 3553 | | }), |
| 3554 | | [WS_METHODS.deviceClose]: (input) => |
| 3555 | | observeRpcEffect(WS_METHODS.deviceClose, deviceService.close(input), { |
| 3556 | | "rpc.aggregate": "device", |
| 3557 | | }), |
| 3558 | | [WS_METHODS.deviceShutdown]: (input) => |
| 3559 | | observeRpcEffect(WS_METHODS.deviceShutdown, deviceService.shutdown(input), { |
| 3560 | | "rpc.aggregate": "device", |
| 3561 | | }), |
| 3562 | | [WS_METHODS.deviceDetail]: (input) => |
| 3563 | | observeRpcEffect(WS_METHODS.deviceDetail, deviceService.detail(input), { |
| 3564 | | "rpc.aggregate": "device", |
| 3565 | | }), |
| 3566 | | [WS_METHODS.deviceAction]: (input) => |
| 3567 | | observeRpcEffect(WS_METHODS.deviceAction, deviceService.action(input), { |
| 3568 | | "rpc.aggregate": "device", |
| 3569 | | }), |
| 3570 | | [WS_METHODS.subscribeDeviceState]: (_input) => |
| 3571 | | observeRpcStream( |
| 3572 | | WS_METHODS.subscribeDeviceState, |
| 3573 | | DeviceService.stateStream(deviceService), |
| 3574 | | { "rpc.aggregate": "device" }, |
| 3575 | | ), |
| 2877 | input.inspectOnly && !input.updateTool |
| 2878 | ? deviceService.inspect |
| 2879 | : authorizeEffect( |
| 2880 | requiredScopeForDeviceList(input), |
| 2881 | input.updateTool |
| 2882 | ? deviceService.updateTool(input.updateTool) |
| 2883 | : input.retryHostId |
| 2884 | ? deviceService.retryHost(input.retryHostId) |
| 2885 | : deviceService.list, |
| 2886 | ), |
| 2887 | [WS_METHODS.deviceOpen]: (input) => deviceService.open(input), |
| 2888 | [WS_METHODS.deviceClose]: (input) => deviceService.close(input), |
| 2889 | [WS_METHODS.deviceShutdown]: (input) => deviceService.shutdown(input), |
| 2890 | [WS_METHODS.deviceDetail]: (input) => deviceService.detail(input), |
| 2891 | [WS_METHODS.deviceAction]: (input) => deviceService.action(input), |
| 2892 | [WS_METHODS.subscribeDeviceState]: (_input) => DeviceService.stateStream(deviceService), |
| 3576 | 2893 | [WS_METHODS.subscribeDiscoveredLocalServers]: (input) => |
| 3577 | | observeRpcStream( |
| 3578 | | WS_METHODS.subscribeDiscoveredLocalServers, |
| 3579 | | Stream.callback<DiscoveredLocalServerList>((queue) => |
| 3580 | | Effect.gen(function* () { |
| 3581 | | const configuredUrls = input.configuredUrls ?? []; |
| 3582 | | yield* portDiscovery.retain; |
| 3583 | | const initial = yield* portDiscovery.scan(configuredUrls); |
| 3584 | | const initialScannedAt = DateTime.formatIso(yield* DateTime.now); |
| 3585 | | yield* Queue.offer(queue, { |
| 3586 | | servers: initial, |
| 3587 | | scannedAt: initialScannedAt, |
| 3588 | | configuredUrlProbing: true, |
| 3589 | | }); |
| 3590 | | yield* portDiscovery.subscribe( |
| 3591 | | { configuredUrls, initialSnapshot: initial }, |
| 3592 | | (servers) => |
| 3593 | | Effect.gen(function* () { |
| 3594 | | const scannedAt = DateTime.formatIso(yield* DateTime.now); |
| 3595 | | yield* Queue.offer(queue, { |
| 3596 | | servers, |
| 3597 | | scannedAt, |
| 3598 | | configuredUrlProbing: true, |
| 3599 | | }); |
| 3600 | | }), |
| 3601 | | ); |
| 3602 | | }), |
| 3603 | | ), |
| 3604 | | { "rpc.aggregate": "preview" }, |
| 2894 | Stream.callback<DiscoveredLocalServerList>((queue) => |
| 2895 | Effect.gen(function* () { |
| 2896 | const configuredUrls = input.configuredUrls ?? []; |
| 2897 | yield* portDiscovery.retain; |
| 2898 | const initial = yield* portDiscovery.scan(configuredUrls); |
| 2899 | const initialScannedAt = DateTime.formatIso(yield* DateTime.now); |
| 2900 | yield* Queue.offer(queue, { |
| 2901 | servers: initial, |
| 2902 | scannedAt: initialScannedAt, |
| 2903 | configuredUrlProbing: true, |
| 2904 | }); |
| 2905 | yield* portDiscovery.subscribe( |
| 2906 | { configuredUrls, initialSnapshot: initial }, |
| 2907 | (servers) => |
| 2908 | Effect.gen(function* () { |
| 2909 | const scannedAt = DateTime.formatIso(yield* DateTime.now); |
| 2910 | yield* Queue.offer(queue, { |
| 2911 | servers, |
| 2912 | scannedAt, |
| 2913 | configuredUrlProbing: true, |
| 2914 | }); |
| 2915 | }), |
| 2916 | ); |
| 2917 | }), |
| 3605 | 2918 | ), |
| 3606 | 2919 | [WS_METHODS.subscribeServerConfig]: (input) => |
| 3607 | | observeRpcStreamEffect( |
| 3608 | | WS_METHODS.subscribeServerConfig, |
| 2920 | Stream.unwrap( |
| 3609 | 2921 | Effect.gen(function* () { |
| 3610 | 2922 | const usageLimitsCommand = input.usageLimitsCommand === true; |
| 3611 | 2923 | const config = yield* loadServerConfig({ usageLimitsCommand }); |
| ... | ... | @@ -3705,11 +3017,9 @@ const layerWsRpc = ( |
| 3705 | 3017 | withLateEditorConfig(config, liveUpdates, externalLauncher), |
| 3706 | 3018 | ); |
| 3707 | 3019 | }), |
| 3708 | | { "rpc.aggregate": "server" }, |
| 3709 | 3020 | ), |
| 3710 | 3021 | [WS_METHODS.subscribeServerLifecycle]: (_input) => |
| 3711 | | observeRpcStreamEffect( |
| 3712 | | WS_METHODS.subscribeServerLifecycle, |
| 3022 | Stream.unwrap( |
| 3713 | 3023 | Effect.gen(function* () { |
| 3714 | 3024 | const liveBuffer = yield* Queue.unbounded<ServerLifecycleStreamEvent>(); |
| 3715 | 3025 | yield* Effect.forkScoped( |
| ... | ... | @@ -3727,11 +3037,9 @@ const layerWsRpc = ( |
| 3727 | 3037 | ); |
| 3728 | 3038 | return Stream.concat(rpcInitialItems(snapshotEvents), liveEvents); |
| 3729 | 3039 | }), |
| 3730 | | { "rpc.aggregate": "server" }, |
| 3731 | 3040 | ), |
| 3732 | 3041 | [WS_METHODS.subscribeAuthAccess]: (_input) => |
| 3733 | | observeRpcStreamEffect( |
| 3734 | | WS_METHODS.subscribeAuthAccess, |
| 3042 | Stream.unwrap( |
| 3735 | 3043 | Effect.gen(function* () { |
| 3736 | 3044 | const initialSnapshot = yield* loadAuthAccessSnapshot(); |
| 3737 | 3045 | const revisionRef = yield* Ref.make(1); |
| ... | ... | @@ -3761,27 +3069,18 @@ const layerWsRpc = ( |
| 3761 | 3069 | liveEvents, |
| 3762 | 3070 | ); |
| 3763 | 3071 | }), |
| 3764 | | { "rpc.aggregate": "auth" }, |
| 3765 | 3072 | ), |
| 3766 | 3073 | [WS_METHODS.subscribeBackgroundPolicy]: (_input) => |
| 3767 | | observeRpcStream( |
| 3768 | | WS_METHODS.subscribeBackgroundPolicy, |
| 3769 | | Stream.unwrap( |
| 3770 | | Effect.map(backgroundPolicy.subscribe, ({ latest, changes }) => |
| 3771 | | Stream.concat(Stream.make(latest), changes), |
| 3772 | | ), |
| 3074 | Stream.unwrap( |
| 3075 | Effect.map(backgroundPolicy.subscribe, ({ latest, changes }) => |
| 3076 | Stream.concat(Stream.make(latest), changes), |
| 3773 | 3077 | ), |
| 3774 | | { "rpc.aggregate": "server" }, |
| 3775 | 3078 | ), |
| 3776 | 3079 | [WS_METHODS.subscribeResourceTelemetry]: (_input) => |
| 3777 | | observeRpcStream( |
| 3778 | | WS_METHODS.subscribeResourceTelemetry, |
| 3779 | | Stream.unwrap( |
| 3780 | | Effect.map(resourceTelemetry.subscribe, ({ latest, changes }) => |
| 3781 | | Stream.concat(Stream.make(latest), changes), |
| 3782 | | ), |
| 3080 | Stream.unwrap( |
| 3081 | Effect.map(resourceTelemetry.subscribe, ({ latest, changes }) => |
| 3082 | Stream.concat(Stream.make(latest), changes), |
| 3783 | 3083 | ), |
| 3784 | | { "rpc.aggregate": "server" }, |
| 3785 | 3084 | ), |
| 3786 | 3085 | }); |
| 3787 | 3086 | return handlers; |
| ... | ... | @@ -3841,7 +3140,9 @@ export const layer = Layer.unwrap( |
| 3841 | 3140 | const { protocol, httpEffect } = yield* RpcServer.makeProtocolWithHttpEffectWebsocket; |
| 3842 | 3141 | yield* RpcServer.make(ServerWsRpcGroup, WS_RPC_SERVER_OPTIONS).pipe( |
| 3843 | 3142 | Effect.provideService(RpcServer.Protocol, withTerminalOutputWindow(protocol)), |
| 3844 | | Effect.provide(RpcAuthorization.layer(session.scopes)), |
| 3143 | Effect.provide( |
| 3144 | Layer.merge(RpcAuthorization.layer(session.scopes), rpcInstrumentationLayer), |
| 3145 | ), |
| 3845 | 3146 | Effect.forkScoped, |
| 3846 | 3147 | ); |
| 3847 | 3148 | // @effect-diagnostics-next-line returnEffectInGen:off |