From 230b39c279f8969decf9b998d4625ac8bb56b22d Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 14 Oct 2026 01:01:37 -0700 Subject: [PATCH] refactor(runtime): organize file search and terminal artifacts by domain (#27571) --- config/scripts/ci-shard-timings.json | 4 +- .../scripts/mobile-file-ranking-benchmark.mjs | 121 ++++++++++++++++-- .../file-paths.ts} | 0 .../file-target.ts} | 12 +- .../search/file-search.test.ts} | 6 +- .../search/file-search.ts} | 28 ++-- .../search/mobile-path-search-expiry.test.ts} | 4 +- .../search/mobile-path-search.test.ts} | 2 +- .../search/mobile-path-search.ts} | 2 +- src/main/runtime/orca-runtime-files.ts | 4 +- .../runtime/runtime-file-command-access.ts | 9 +- src/main/runtime/runtime-file-command-host.ts | 7 +- ...nds-create-file-explorer-dir-no-clobber.ts | 5 +- ...me-file-commands-mobile-file-list-limit.ts | 2 +- ...ile-commands-read-file-explorer-preview.ts | 5 +- .../runtime-file-commands-read-mobile-file.ts | 4 +- ...ime-file-commands-resolve-terminal-path.ts | 5 +- ...ntime-file-commands-terminal-file-paths.ts | 4 +- ...-file-commands-write-file-explorer-file.ts | 2 +- .../runtime-file-explorer-watch-commands.ts | 2 +- .../runtime/runtime-file-path-existence.ts | 2 +- .../runtime-file-upload-decode.test.ts | 2 +- .../artifacts/artifact-integrity.ts} | 6 +- .../artifacts/artifact-stat.ts} | 6 +- .../artifacts/artifact-write.ts} | 14 +- .../artifacts/file-grants.test.ts} | 7 +- .../artifacts/file-grants.ts} | 10 +- .../artifacts/terminal-artifacts.ts} | 22 ++-- 28 files changed, 185 insertions(+), 112 deletions(-) rename src/main/runtime/{runtime-file-paths.ts => files/file-paths.ts} (100%) rename src/main/runtime/{runtime-file-command-target.ts => files/file-target.ts} (90%) rename src/main/runtime/{runtime-file-search.test.ts => files/search/file-search.test.ts} (93%) rename src/main/runtime/{runtime-file-search.ts => files/search/file-search.ts} (90%) rename src/main/runtime/{runtime-mobile-file-path-search-expiry.test.ts => files/search/mobile-path-search-expiry.test.ts} (98%) rename src/main/runtime/{runtime-mobile-file-path-search.test.ts => files/search/mobile-path-search.test.ts} (99%) rename src/main/runtime/{runtime-mobile-file-path-search.ts => files/search/mobile-path-search.ts} (98%) rename src/main/runtime/{runtime-terminal-artifact-integrity.ts => terminal/artifacts/artifact-integrity.ts} (95%) rename src/main/runtime/{runtime-terminal-artifact-stat.ts => terminal/artifacts/artifact-stat.ts} (78%) rename src/main/runtime/{runtime-terminal-artifact-write.ts => terminal/artifacts/artifact-write.ts} (84%) rename src/main/runtime/{runtime-terminal-file-grants.test.ts => terminal/artifacts/file-grants.test.ts} (96%) rename src/main/runtime/{runtime-terminal-file-grants.ts => terminal/artifacts/file-grants.ts} (95%) rename src/main/runtime/{runtime-terminal-artifacts.ts => terminal/artifacts/terminal-artifacts.ts} (86%) diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index 924d3225032..e8203d6ab5f 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -4909,8 +4909,8 @@ "src/main/runtime/runtime-metadata-ownership-watch.test.ts": 116, "src/main/runtime/runtime-metadata.test.ts": 380, "src/main/runtime/runtime-mobile-agent-status-builder.test.ts": 91, - "src/main/runtime/runtime-mobile-file-path-search-expiry.test.ts": 223, - "src/main/runtime/runtime-mobile-file-path-search.test.ts": 75, + "src/main/runtime/files/search/mobile-path-search-expiry.test.ts": 223, + "src/main/runtime/files/search/mobile-path-search.test.ts": 75, "src/main/runtime/runtime-mobile-session-incarnation-projection.test.ts": 80, "src/main/runtime/runtime-orchestration-sender-names.test.ts": 948, "src/main/runtime/runtime-owned-terminal-publication-lineage.test.ts": 5659, diff --git a/config/scripts/mobile-file-ranking-benchmark.mjs b/config/scripts/mobile-file-ranking-benchmark.mjs index 27bf99f8ecd..37e3b3ae896 100644 --- a/config/scripts/mobile-file-ranking-benchmark.mjs +++ b/config/scripts/mobile-file-ranking-benchmark.mjs @@ -1,10 +1,12 @@ import assert from 'node:assert/strict' -import { execFileSync } from 'node:child_process' import { readFileSync } from 'node:fs' +import path from 'node:path' import { performance } from 'node:perf_hooks' -import { transform } from 'esbuild' +import { build } from 'esbuild' +import { runProcessSync } from '@orca/process-host' import { buildCounterbalancedSchedule } from './counterbalanced-benchmark-schedule.mjs' import { summarizeBenchmarkSamples } from './benchmark-sample-summary.mjs' +import { describeProcessFailure } from './process-failure-message.mjs' const baseline = process.argv[2] if (!baseline) { @@ -14,27 +16,122 @@ if (!baseline) { } // git show :mobile/src/session/mobile-native-chat-autocomplete.ts | node config/scripts/mobile-file-ranking-benchmark.mjs --autocomplete-stdin const autocompleteSource = baseline === '--autocomplete-stdin' ? readFileSync(0, 'utf8') : null -async function load(source) { - const { code } = await transform(source, { loader: 'ts', format: 'esm' }) +const root = path.resolve(import.meta.dirname, '../..') +function git(args) { + return runProcessSync({ + program: 'git', + args, + cwd: root, + timeoutMs: 30_000, + maxOutputBytes: 2 * 1024 * 1024 + }) +} +function readGit(args) { + const result = git(args) + if (result.code !== 0 || result.timedOut || result.outputTruncated) { + throw new Error(describeProcessFailure(result)) + } + return result.stdout +} +const baselineCommit = + autocompleteSource === null + ? readGit(['rev-parse', '--verify', `${baseline}^{commit}`]).trim() + : null +function resolveBaselineFile(candidates) { + for (const file of candidates) { + const result = git(['cat-file', '-t', `${baselineCommit}:${file}`]) + if (result.timedOut || result.outputTruncated || ![0, 128].includes(result.code)) { + throw new Error(describeProcessFailure(result)) + } + if (result.code === 0 && result.stdout.trim() === 'blob') { + return file + } + } + throw new Error(`Missing baseline source: ${candidates.join(', ')}`) +} +/** + * @param {string} file + * @param {string | null} ref + * @param {string | null} source + */ +async function load(file, ref = null, source = null) { + const { outputFiles } = await build({ + ...(source === null + ? { entryPoints: [file] } + : { + stdin: { + contents: source, + sourcefile: file, + resolveDir: path.dirname(path.resolve(root, file)), + loader: 'ts' + } + }), + absWorkingDir: root, + bundle: source === null, + tsconfigRaw: {}, + write: false, + platform: 'node', + format: 'esm', + plugins: + ref === null + ? [] + : [ + { + name: 'exact-baseline-ranking-source', + setup(builder) { + builder.onResolve({ filter: /.*/ }, (args) => { + if (args.kind === 'entry-point') { + return { path: file, namespace: 'git-baseline' } + } + if (args.namespace !== 'git-baseline') { + return undefined + } + if (!args.path.startsWith('.')) { + return { path: args.path, external: true } + } + const target = path.posix.join(path.posix.dirname(args.importer), args.path) + return { + path: resolveBaselineFile([ + target, + `${target}.ts`, + `${target}.tsx`, + `${target}.js`, + `${target}/index.ts` + ]), + namespace: 'git-baseline' + } + }) + builder.onLoad({ filter: /.*/, namespace: 'git-baseline' }, (args) => ({ + contents: readGit(['show', `${ref}:${args.path}`]), + loader: args.path.endsWith('.tsx') ? 'tsx' : 'ts' + })) + } + } + ] + }) + const code = outputFiles[0].text return await import(`data:text/javascript;base64,${Buffer.from(code).toString('base64')}`) } const results = [] let differentialCases = 0 for (const [file, name] of [ - ['src/main/runtime/runtime-mobile-file-path-search.ts', 'rankRuntimeMobileFilePaths'], + ['src/main/runtime/files/search/mobile-path-search.ts', 'rankRuntimeMobileFilePaths'], ['mobile/src/session/mobile-native-chat-autocomplete.ts', 'rankSuggestions'], ['mobile/src/session/mobile-native-chat-autocomplete.ts', 'rankSlashCommandSuggestions'] ]) { if (autocompleteSource !== null && name === 'rankRuntimeMobileFilePaths') { continue } - const before = ( - await load( - autocompleteSource ?? - execFileSync('git', ['show', `${baseline}:${file}`], { encoding: 'utf8' }) - ) - )[name] - const after = (await load(readFileSync(file, 'utf8')))[name] + const baselineFile = + autocompleteSource === null + ? resolveBaselineFile( + name === 'rankRuntimeMobileFilePaths' + ? [file, 'src/main/runtime/runtime-mobile-file-path-search.ts'] + : [file] + ) + : file + const before = (await load(baselineFile, baselineCommit, autocompleteSource))[name] + const after = (await load(file))[name] const slash = name === 'rankSlashCommandSuggestions' const toCandidates = (names) => slash ? names.map((name, index) => ({ name, description: `Command ${index}` })) : names diff --git a/src/main/runtime/runtime-file-paths.ts b/src/main/runtime/files/file-paths.ts similarity index 100% rename from src/main/runtime/runtime-file-paths.ts rename to src/main/runtime/files/file-paths.ts diff --git a/src/main/runtime/runtime-file-command-target.ts b/src/main/runtime/files/file-target.ts similarity index 90% rename from src/main/runtime/runtime-file-command-target.ts rename to src/main/runtime/files/file-target.ts index 4c8bed27790..b3665e683c7 100644 --- a/src/main/runtime/runtime-file-command-target.ts +++ b/src/main/runtime/files/file-target.ts @@ -1,16 +1,16 @@ -import type { ExecutionHostId } from '../../shared/execution-host' -import type { GitWorktreeInfo, Worktree } from '../../shared/worktree/types' +import type { ExecutionHostId } from '../../../shared/execution-host' +import type { GitWorktreeInfo, Worktree } from '../../../shared/worktree/types' import { ExecutionHostNotDispatchableError, resolveFilesystemRouteForHost -} from '../providers/execution-host-provider-dispatch' -import { resolveAuthorizedPath } from '../ipc/filesystem-auth' +} from '../../providers/execution-host-provider-dispatch' +import { resolveAuthorizedPath } from '../../ipc/filesystem-auth' import type { createLocalFilesystemProvider, LocalFilesystemProvider, LocalFilesystemProviderOptions -} from '../providers/local-filesystem-provider' -import { SshHostNotServedError } from '../providers/ssh-host-not-served-error' +} from '../../providers/local-filesystem-provider' +import { SshHostNotServedError } from '../../providers/ssh-host-not-served-error' export type ResolvedRuntimeFileWorktree = Worktree & { git: GitWorktreeInfo } diff --git a/src/main/runtime/runtime-file-search.test.ts b/src/main/runtime/files/search/file-search.test.ts similarity index 93% rename from src/main/runtime/runtime-file-search.test.ts rename to src/main/runtime/files/search/file-search.test.ts index 203da0ba189..6ee6cbe6534 100644 --- a/src/main/runtime/runtime-file-search.test.ts +++ b/src/main/runtime/files/search/file-search.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, vi } from 'vitest' -import { ExecutionHostNotDispatchableError } from '../providers/execution-host-provider-dispatch' -import { SSH_HOST_NOT_SERVED_MESSAGE } from '../providers/ssh-host-not-served-error' -import { RuntimeFileSearch, type RuntimeFileSearchHost } from './runtime-file-search' +import { ExecutionHostNotDispatchableError } from '../../../providers/execution-host-provider-dispatch' +import { SSH_HOST_NOT_SERVED_MESSAGE } from '../../../providers/ssh-host-not-served-error' +import { RuntimeFileSearch, type RuntimeFileSearchHost } from './file-search' function createSearch(executionHostId: 'local' | 'ssh:unavailable' | 'runtime:other' = 'local') { const requireStore = vi.fn(() => { diff --git a/src/main/runtime/runtime-file-search.ts b/src/main/runtime/files/search/file-search.ts similarity index 90% rename from src/main/runtime/runtime-file-search.ts rename to src/main/runtime/files/search/file-search.ts index 0f4db71d1fe..fbf2ed86de8 100644 --- a/src/main/runtime/runtime-file-search.ts +++ b/src/main/runtime/files/search/file-search.ts @@ -1,30 +1,30 @@ import { QUICK_OPEN_SEARCH_VERSION, isQuickOpenQueryTooLarge -} from '../../shared/quick-open-path-search' -import type { RuntimeFileListResult } from '../../shared/runtime-types' -import type { SearchOptions, SearchResult } from '../../shared/code-search-types' -import { throwIfSignalAborted, waitForPromiseWithSignal } from '../../shared/abort-signal-reason' -import { listQuickOpenFiles } from '../ipc/filesystem-list-files' -import { searchQuickOpenFilePaths as searchHostQuickOpenFilePaths } from '../ipc/filesystem-search-file-paths' -import { isMobileBinaryPath, isSafeMobileRelativePath } from './runtime-file-command-host' +} from '../../../../shared/quick-open-path-search' +import type { RuntimeFileListResult } from '../../../../shared/runtime-types' +import type { SearchOptions, SearchResult } from '../../../../shared/code-search-types' +import { + throwIfSignalAborted, + waitForPromiseWithSignal +} from '../../../../shared/abort-signal-reason' +import { listQuickOpenFiles } from '../../../ipc/filesystem-list-files' +import { searchQuickOpenFilePaths as searchHostQuickOpenFilePaths } from '../../../ipc/filesystem-search-file-paths' +import { isMobileBinaryPath, isSafeMobileRelativePath } from '../../runtime-file-command-host' import { requireRuntimeFileProvider, runtimeFileRouteForTarget, type RuntimeLocalFileHost, type ResolvedRuntimeFileTarget -} from './runtime-file-command-target' +} from '../file-target' import { MOBILE_FILE_LIST_LIMIT, MOBILE_FILE_PATH_SEARCH_CACHE_LIMIT, MOBILE_FILE_PATH_SEARCH_CACHE_ENTRIES, MOBILE_FILE_PATH_SEARCH_CACHE_TTL_MS -} from './runtime-file-commands-mobile-file-list-limit' -import { basenameFromRelativePath } from './runtime-file-paths' -import { - RuntimeMobileFilePathSearchCache, - rankRuntimeMobileFilePaths -} from './runtime-mobile-file-path-search' +} from '../../runtime-file-commands-mobile-file-list-limit' +import { basenameFromRelativePath } from '../file-paths' +import { RuntimeMobileFilePathSearchCache, rankRuntimeMobileFilePaths } from './mobile-path-search' type RuntimeFileSearchTarget = { worktree: Pick diff --git a/src/main/runtime/runtime-mobile-file-path-search-expiry.test.ts b/src/main/runtime/files/search/mobile-path-search-expiry.test.ts similarity index 98% rename from src/main/runtime/runtime-mobile-file-path-search-expiry.test.ts rename to src/main/runtime/files/search/mobile-path-search-expiry.test.ts index db800eb84f3..6916909919e 100644 --- a/src/main/runtime/runtime-mobile-file-path-search-expiry.test.ts +++ b/src/main/runtime/files/search/mobile-path-search-expiry.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { MAX_TIMER_DELAY_MS } from '../../shared/timer-delay' +import { MAX_TIMER_DELAY_MS } from '../../../../shared/timer-delay' import { RuntimeMobileFilePathSearchCache, type RuntimeMobileFilePathInventory -} from './runtime-mobile-file-path-search' +} from './mobile-path-search' const TTL_MS = 30_000 diff --git a/src/main/runtime/runtime-mobile-file-path-search.test.ts b/src/main/runtime/files/search/mobile-path-search.test.ts similarity index 99% rename from src/main/runtime/runtime-mobile-file-path-search.test.ts rename to src/main/runtime/files/search/mobile-path-search.test.ts index 0be5ecad50e..29eed38b7f4 100644 --- a/src/main/runtime/runtime-mobile-file-path-search.test.ts +++ b/src/main/runtime/files/search/mobile-path-search.test.ts @@ -3,7 +3,7 @@ import { rankRuntimeMobileFilePaths, type RuntimeMobileFilePathInventory, RuntimeMobileFilePathSearchCache -} from './runtime-mobile-file-path-search' +} from './mobile-path-search' describe('rankRuntimeMobileFilePaths', () => { it('preserves basename matching, ordering and total counts for unusual paths', () => { diff --git a/src/main/runtime/runtime-mobile-file-path-search.ts b/src/main/runtime/files/search/mobile-path-search.ts similarity index 98% rename from src/main/runtime/runtime-mobile-file-path-search.ts rename to src/main/runtime/files/search/mobile-path-search.ts index 5955ad5ec39..018135d968c 100644 --- a/src/main/runtime/runtime-mobile-file-path-search.ts +++ b/src/main/runtime/files/search/mobile-path-search.ts @@ -1,4 +1,4 @@ -import { MAX_TIMER_DELAY_MS } from '../../shared/timer-delay' +import { MAX_TIMER_DELAY_MS } from '../../../../shared/timer-delay' export type RuntimeMobileFilePathInventory = { paths: string[] diff --git a/src/main/runtime/orca-runtime-files.ts b/src/main/runtime/orca-runtime-files.ts index 6d030df33b0..6114fa82951 100644 --- a/src/main/runtime/orca-runtime-files.ts +++ b/src/main/runtime/orca-runtime-files.ts @@ -6,7 +6,7 @@ export { WINDOWS_RUNTIME_FILE_WATCH_CLOSE_DEADLINE_MS } from './runtime-file-com export { awaitRuntimeFileWatcherUnsubscribes } from './runtime-file-watcher-leases' export { _getRuntimeFileWatcherReleaseCountForTests } from './runtime-file-watcher-leases' export { _resetRuntimeFileWatcherLeasesForTests } from './runtime-file-watcher-leases' -export type { ResolvedRuntimeFileWorktree } from './runtime-file-command-target' -export type { ResolvedRuntimeFileTarget } from './runtime-file-command-target' +export type { ResolvedRuntimeFileWorktree } from './files/file-target' +export type { ResolvedRuntimeFileTarget } from './files/file-target' export type { RuntimeFileCommandHost } from './runtime-file-command-host' export { isSafeMobileRelativePath } from './runtime-file-command-host' diff --git a/src/main/runtime/runtime-file-command-access.ts b/src/main/runtime/runtime-file-command-access.ts index 6f12a21aa32..edf273c8042 100644 --- a/src/main/runtime/runtime-file-command-access.ts +++ b/src/main/runtime/runtime-file-command-access.ts @@ -1,6 +1,6 @@ +import { RuntimeTerminalArtifacts } from './terminal/artifacts/terminal-artifacts' +import { RuntimeFileSearch } from './files/search/file-search' import type { RuntimeFileOpenPosition } from '../../shared/runtime-file-contracts' -import { RuntimeTerminalArtifacts } from './runtime-terminal-artifacts' -import { RuntimeFileSearch } from './runtime-file-search' import { listFilesystemMarkdownDocuments } from '../providers/filesystem-markdown-listing' import type { MarkdownDocument } from '../../shared/filesystem-entry-types' import { @@ -19,10 +19,7 @@ import type { RuntimeNavigationTarget } from '../../shared/runtime-navigation' import { isMobilePreviewableImagePath } from './runtime-file-commands-mobile-file-list-limit' import { joinWorktreeRelativePath, normalizeRuntimeRelativePath } from './runtime-relative-paths' import { isENOENT } from '../ipc/filesystem-path-containment' -import { - requireRuntimeFileProvider, - type RuntimeFileExplorerPath -} from './runtime-file-command-target' +import { requireRuntimeFileProvider, type RuntimeFileExplorerPath } from './files/file-target' import { parseExecutionHostId, type ExecutionHostId } from '../../shared/execution-host' import type { FileStat } from '../providers/filesystem-provider-contract' diff --git a/src/main/runtime/runtime-file-command-host.ts b/src/main/runtime/runtime-file-command-host.ts index a9c05470783..175e553ee1a 100644 --- a/src/main/runtime/runtime-file-command-host.ts +++ b/src/main/runtime/runtime-file-command-host.ts @@ -1,10 +1,7 @@ // @ts-nocheck -- mechanically split declarations. import type { RuntimeFileOpenPosition } from '../../shared/runtime-file-contracts' import type { Store } from '../persistence' -import type { - ResolvedRuntimeFileTarget, - ResolvedRuntimeFileWorktree -} from './runtime-file-command-target' +import type { ResolvedRuntimeFileTarget, ResolvedRuntimeFileWorktree } from './files/file-target' import type { ExecutionHostId } from '../../shared/execution-host' import type { RuntimeNativeChatFileContext } from '../../shared/runtime-types' import type { RuntimeNavigationTarget } from '../../shared/runtime-navigation' @@ -17,7 +14,7 @@ import { } from './runtime-file-commands-mobile-file-list-limit' import { watch as watchFs } from 'node:fs' import { WatcherProcessFailure } from '../ipc/parcel-watcher-process-failure' -import { basenameFromRelativePath } from './runtime-file-paths' +import { basenameFromRelativePath } from './files/file-paths' export type RuntimeFileCommandHost = { getRuntimeId(): string diff --git a/src/main/runtime/runtime-file-commands-create-file-explorer-dir-no-clobber.ts b/src/main/runtime/runtime-file-commands-create-file-explorer-dir-no-clobber.ts index 6bb924b3648..935296320fb 100644 --- a/src/main/runtime/runtime-file-commands-create-file-explorer-dir-no-clobber.ts +++ b/src/main/runtime/runtime-file-commands-create-file-explorer-dir-no-clobber.ts @@ -1,10 +1,7 @@ // @ts-nocheck -- mechanically split class members. import { RuntimeFileCommandsWithWriteFileExplorerFile } from './runtime-file-commands-write-file-explorer-file' import { assertRuntimeFileMutationExpectation } from './runtime-file-commands-mobile-file-list-limit' -import { - requireLocalRuntimeFileRoute, - requireRuntimeFileProvider -} from './runtime-file-command-target' +import { requireLocalRuntimeFileRoute, requireRuntimeFileProvider } from './files/file-target' import { resolveAuthorizedPath } from '../ipc/filesystem-auth' import { constants, copyFile, mkdir, rm } from 'node:fs/promises' import { dirname } from 'node:path' diff --git a/src/main/runtime/runtime-file-commands-mobile-file-list-limit.ts b/src/main/runtime/runtime-file-commands-mobile-file-list-limit.ts index 505a6142e97..256e2216961 100644 --- a/src/main/runtime/runtime-file-commands-mobile-file-list-limit.ts +++ b/src/main/runtime/runtime-file-commands-mobile-file-list-limit.ts @@ -7,7 +7,7 @@ import { import { constants } from 'node:fs/promises' import { getSshTargetIdForExecutionHost, type ExecutionHostId } from '../../shared/execution-host' import { assertSshMutationExpectation } from '../ssh/ssh-connection-generation' -import { basenameFromRelativePath } from './runtime-file-paths' +import { basenameFromRelativePath } from './files/file-paths' import { normalizeRuntimePathForComparison } from '../../shared/cross-platform-path' export const MOBILE_FILE_LIST_LIMIT = 5000 diff --git a/src/main/runtime/runtime-file-commands-read-file-explorer-preview.ts b/src/main/runtime/runtime-file-commands-read-file-explorer-preview.ts index 03df5368f3a..4be5109f562 100644 --- a/src/main/runtime/runtime-file-commands-read-file-explorer-preview.ts +++ b/src/main/runtime/runtime-file-commands-read-file-explorer-preview.ts @@ -11,10 +11,7 @@ import { assertPreviewWithinTransportBudget, previewableBinaryByteLimit } from './runtime-file-commands-mobile-file-list-limit' -import { - requireLocalRuntimeFileRoute, - requireRuntimeFileProvider -} from './runtime-file-command-target' +import { requireLocalRuntimeFileRoute, requireRuntimeFileProvider } from './files/file-target' import { readLocalFileRange } from '../ipc/filesystem/local-file-range-read' import { resolveAuthorizedPath } from '../ipc/filesystem-auth' import { extname } from 'node:path' diff --git a/src/main/runtime/runtime-file-commands-read-mobile-file.ts b/src/main/runtime/runtime-file-commands-read-mobile-file.ts index 6fe3a8f30e8..80d40d163d1 100644 --- a/src/main/runtime/runtime-file-commands-read-mobile-file.ts +++ b/src/main/runtime/runtime-file-commands-read-mobile-file.ts @@ -3,8 +3,8 @@ import type { RuntimeFileReadResult } from '../../shared/runtime-types' import { isMobileBinaryPath, isSafeMobileRelativePath } from './runtime-file-command-host' import { joinWorktreeRelativePath } from './runtime-relative-paths' import { readLocalMobileFile } from './runtime-file-commands-terminal-file-paths' -import { truncateMobileFilePreview } from './runtime-terminal-artifact-integrity' -import { requireLocalRuntimeFileRoute } from './runtime-file-command-target' +import { truncateMobileFilePreview } from './terminal/artifacts/artifact-integrity' +import { requireLocalRuntimeFileRoute } from './files/file-target' export class RuntimeFileCommandsWithReadMobileFile extends RuntimeFileCommandAccess { async readMobileFile( diff --git a/src/main/runtime/runtime-file-commands-resolve-terminal-path.ts b/src/main/runtime/runtime-file-commands-resolve-terminal-path.ts index e357bf9ecad..b9cc2361636 100644 --- a/src/main/runtime/runtime-file-commands-resolve-terminal-path.ts +++ b/src/main/runtime/runtime-file-commands-resolve-terminal-path.ts @@ -11,10 +11,7 @@ import { provenancePathCandidate, resolveTerminalAbsolutePath } from './runtime-file-commands-terminal-file-paths' -import { - requireRuntimeFileProvider, - runtimeFileRouteForTarget -} from './runtime-file-command-target' +import { requireRuntimeFileProvider, runtimeFileRouteForTarget } from './files/file-target' import { isSafeMobileRelativePath } from './runtime-file-command-host' import { isENOENT } from '../ipc/filesystem-path-containment' diff --git a/src/main/runtime/runtime-file-commands-terminal-file-paths.ts b/src/main/runtime/runtime-file-commands-terminal-file-paths.ts index f1a64c86e32..5998044de07 100644 --- a/src/main/runtime/runtime-file-commands-terminal-file-paths.ts +++ b/src/main/runtime/runtime-file-commands-terminal-file-paths.ts @@ -3,7 +3,7 @@ import { open, stat } from 'node:fs/promises' import { extname } from 'node:path' import type { Store } from '../persistence' import { resolveAuthorizedPath } from '../ipc/filesystem-auth' -import type { TerminalFileGrant } from './runtime-terminal-file-grants' +import type { TerminalFileGrant } from './terminal/artifacts/file-grants' import { LOCAL_PREVIEWABLE_BINARY_MAX_BYTES, MOBILE_FILE_READ_MAX_BYTES, @@ -18,7 +18,7 @@ import { canonicalPathForArtifactComparison, localTerminalArtifactRoots, readFileHandleBufferBounded -} from './runtime-terminal-artifact-integrity' +} from './terminal/artifacts/artifact-integrity' import { isBinaryBuffer } from '../../shared/binary-buffer' import type { RuntimeFilePreviewResult } from '../../shared/runtime-types' import { diff --git a/src/main/runtime/runtime-file-commands-write-file-explorer-file.ts b/src/main/runtime/runtime-file-commands-write-file-explorer-file.ts index 52168c5baf1..548e238aac7 100644 --- a/src/main/runtime/runtime-file-commands-write-file-explorer-file.ts +++ b/src/main/runtime/runtime-file-commands-write-file-explorer-file.ts @@ -1,7 +1,7 @@ // @ts-nocheck -- mechanically split class members. import { RuntimeFileCommandsWithReadFileExplorerPreview } from './runtime-file-commands-read-file-explorer-preview' import { assertRuntimeFileMutationExpectation } from './runtime-file-commands-mobile-file-list-limit' -import { requireRuntimeFileProvider } from './runtime-file-command-target' +import { requireRuntimeFileProvider } from './files/file-target' export class RuntimeFileCommandsWithWriteFileExplorerFile extends RuntimeFileCommandsWithReadFileExplorerPreview { async writeFileExplorerFile( diff --git a/src/main/runtime/runtime-file-explorer-watch-commands.ts b/src/main/runtime/runtime-file-explorer-watch-commands.ts index ce897b7aa09..b9b1eb23d34 100644 --- a/src/main/runtime/runtime-file-explorer-watch-commands.ts +++ b/src/main/runtime/runtime-file-explorer-watch-commands.ts @@ -7,7 +7,7 @@ import { requireLocalRuntimeFileRoute, requireRuntimeFileProvider, runtimeFileSshTargetId -} from './runtime-file-command-target' +} from './files/file-target' import { stat } from 'node:fs/promises' import type { DirEntry, FsChangeEvent } from '../../shared/filesystem-entry-types' import { sortDirEntries } from '../../shared/file-name-sort' diff --git a/src/main/runtime/runtime-file-path-existence.ts b/src/main/runtime/runtime-file-path-existence.ts index 903cb7b0af1..a480964cae8 100644 --- a/src/main/runtime/runtime-file-path-existence.ts +++ b/src/main/runtime/runtime-file-path-existence.ts @@ -4,7 +4,7 @@ import { requireRuntimeFileProvider, type RuntimeFileExplorerPath, type RuntimeLocalFileHost -} from './runtime-file-command-target' +} from './files/file-target' export async function readRuntimeFilePathExistence( targets: readonly RuntimeFileExplorerPath[], diff --git a/src/main/runtime/runtime-file-upload-decode.test.ts b/src/main/runtime/runtime-file-upload-decode.test.ts index cc018eeecf9..c5237eec1a6 100644 --- a/src/main/runtime/runtime-file-upload-decode.test.ts +++ b/src/main/runtime/runtime-file-upload-decode.test.ts @@ -22,7 +22,7 @@ vi.mock('./runtime-file-commands-read-file-explorer-preview', () => ({ vi.mock('./runtime-file-commands-mobile-file-list-limit', () => ({ assertRuntimeFileMutationExpectation: mocks.expectation })) -vi.mock('./runtime-file-command-target', () => ({ requireRuntimeFileProvider: mocks.provider })) +vi.mock('./files/file-target', () => ({ requireRuntimeFileProvider: mocks.provider })) vi.mock('../ipc/filesystem-auth', () => ({ resolveAuthorizedPath: mocks.authorize })) vi.mock('node:fs/promises', async (importOriginal) => ({ ...(await importOriginal()), diff --git a/src/main/runtime/runtime-terminal-artifact-integrity.ts b/src/main/runtime/terminal/artifacts/artifact-integrity.ts similarity index 95% rename from src/main/runtime/runtime-terminal-artifact-integrity.ts rename to src/main/runtime/terminal/artifacts/artifact-integrity.ts index 409dadbfb98..e37ada748eb 100644 --- a/src/main/runtime/runtime-terminal-artifact-integrity.ts +++ b/src/main/runtime/terminal/artifacts/artifact-integrity.ts @@ -1,13 +1,13 @@ import { tmpdir } from 'node:os' import { createHash } from 'node:crypto' -import { parseWslPath, toWindowsWslPath } from '../wsl' +import { parseWslPath, toWindowsWslPath } from '../../../wsl' import { realpath } from 'node:fs/promises' import type { FileHandle } from 'node:fs/promises' -import type { RuntimeFileStatLike, TerminalFileGrant } from './runtime-terminal-file-grants' +import type { RuntimeFileStatLike, TerminalFileGrant } from './file-grants' import { LOCAL_PREVIEWABLE_BINARY_MAX_BYTES, MOBILE_FILE_READ_MAX_BYTES -} from './runtime-file-commands-mobile-file-list-limit' +} from '../../runtime-file-commands-mobile-file-list-limit' export async function localTerminalArtifactRoots(worktreePath: string): Promise { const roots = new Set([tmpdir()]) diff --git a/src/main/runtime/runtime-terminal-artifact-stat.ts b/src/main/runtime/terminal/artifacts/artifact-stat.ts similarity index 78% rename from src/main/runtime/runtime-terminal-artifact-stat.ts rename to src/main/runtime/terminal/artifacts/artifact-stat.ts index 6b6fe1dd1d9..167fd47d10b 100644 --- a/src/main/runtime/runtime-terminal-artifact-stat.ts +++ b/src/main/runtime/terminal/artifacts/artifact-stat.ts @@ -1,7 +1,7 @@ import { open } from 'node:fs/promises' -import { assertLocalTerminalArtifactPathStillCanonical } from './runtime-file-commands-terminal-file-paths' -import { localTerminalArtifactContentDigest } from './runtime-terminal-artifact-integrity' -import type { RuntimeFileStatLike } from './runtime-terminal-file-grants' +import { assertLocalTerminalArtifactPathStillCanonical } from '../../runtime-file-commands-terminal-file-paths' +import { localTerminalArtifactContentDigest } from './artifact-integrity' +import type { RuntimeFileStatLike } from './file-grants' /** Stat and content digest come from one handle to retain the existing swap protection. */ export async function statLocalTerminalArtifact(absolutePath: string): Promise<{ diff --git a/src/main/runtime/runtime-terminal-artifact-write.ts b/src/main/runtime/terminal/artifacts/artifact-write.ts similarity index 84% rename from src/main/runtime/runtime-terminal-artifact-write.ts rename to src/main/runtime/terminal/artifacts/artifact-write.ts index fddbe40f4a1..2afd98c3d1e 100644 --- a/src/main/runtime/runtime-terminal-artifact-write.ts +++ b/src/main/runtime/terminal/artifacts/artifact-write.ts @@ -1,18 +1,18 @@ import { chmod, constants, rename, rm, writeFile } from 'node:fs/promises' import { basename, dirname, join } from 'node:path' import { randomUUID } from 'node:crypto' -import type { RuntimeTerminalFileGrants } from './runtime-terminal-file-grants' -import { MOBILE_FILE_READ_MAX_BYTES } from './runtime-file-commands-mobile-file-list-limit' -import { isMobileBinaryPath } from './runtime-file-command-host' -import { isBinaryBuffer } from '../../shared/binary-buffer' -import { openLocalTerminalArtifactGrant } from './runtime-file-commands-terminal-file-paths' +import type { RuntimeTerminalFileGrants } from './file-grants' +import { MOBILE_FILE_READ_MAX_BYTES } from '../../runtime-file-commands-mobile-file-list-limit' +import { isMobileBinaryPath } from '../../runtime-file-command-host' +import { isBinaryBuffer } from '../../../../shared/binary-buffer' +import { openLocalTerminalArtifactGrant } from '../../runtime-file-commands-terminal-file-paths' import { assertTerminalArtifactContentUnchanged, assertTerminalFileGrantFresh, readFileHandleBufferBounded, terminalFileStatIdentity -} from './runtime-terminal-artifact-integrity' -import { statLocalTerminalArtifact } from './runtime-terminal-artifact-stat' +} from './artifact-integrity' +import { statLocalTerminalArtifact } from './artifact-stat' export async function writeTerminalArtifactFile( grants: Pick, diff --git a/src/main/runtime/runtime-terminal-file-grants.test.ts b/src/main/runtime/terminal/artifacts/file-grants.test.ts similarity index 96% rename from src/main/runtime/runtime-terminal-file-grants.test.ts rename to src/main/runtime/terminal/artifacts/file-grants.test.ts index ecf91fc0889..3b0b970edc6 100644 --- a/src/main/runtime/runtime-terminal-file-grants.test.ts +++ b/src/main/runtime/terminal/artifacts/file-grants.test.ts @@ -1,11 +1,8 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { ExecutionHostNotDispatchableError } from '../providers/execution-host-provider-dispatch' -import { - RuntimeTerminalFileGrants, - type RuntimeTerminalFileGrantHost -} from './runtime-terminal-file-grants' +import { ExecutionHostNotDispatchableError } from '../../../providers/execution-host-provider-dispatch' +import { RuntimeTerminalFileGrants, type RuntimeTerminalFileGrantHost } from './file-grants' const artifactPath = join(tmpdir(), 'orca-grant-ownership.txt') const ttl = 10 * 60 * 1000 diff --git a/src/main/runtime/runtime-terminal-file-grants.ts b/src/main/runtime/terminal/artifacts/file-grants.ts similarity index 95% rename from src/main/runtime/runtime-terminal-file-grants.ts rename to src/main/runtime/terminal/artifacts/file-grants.ts index 0952603afa7..b2971de22b7 100644 --- a/src/main/runtime/runtime-terminal-file-grants.ts +++ b/src/main/runtime/terminal/artifacts/file-grants.ts @@ -1,12 +1,6 @@ import { randomUUID } from 'node:crypto' -import { - assertTerminalArtifactNotHardLinked, - terminalFileStatIdentity -} from './runtime-terminal-artifact-integrity' -import { - runtimeFileSshTargetId, - type ResolvedRuntimeFileTarget -} from './runtime-file-command-target' +import { assertTerminalArtifactNotHardLinked, terminalFileStatIdentity } from './artifact-integrity' +import { runtimeFileSshTargetId, type ResolvedRuntimeFileTarget } from '../../files/file-target' const TERMINAL_FILE_GRANT_TTL_MS = 10 * 60 * 1000 diff --git a/src/main/runtime/runtime-terminal-artifacts.ts b/src/main/runtime/terminal/artifacts/terminal-artifacts.ts similarity index 86% rename from src/main/runtime/runtime-terminal-artifacts.ts rename to src/main/runtime/terminal/artifacts/terminal-artifacts.ts index 9dd0ec1a355..c431128f1d2 100644 --- a/src/main/runtime/runtime-terminal-artifacts.ts +++ b/src/main/runtime/terminal/artifacts/terminal-artifacts.ts @@ -3,30 +3,30 @@ import { RuntimeTerminalFileGrants, type RuntimeTerminalFileGrantHost, type TerminalFileGrant -} from './runtime-terminal-file-grants' +} from './file-grants' import type { RuntimeFilePreviewResult, RuntimeFileReadResult, RuntimeTerminalPathResolution -} from '../../shared/runtime-file-contracts' +} from '../../../../shared/runtime-file-contracts' import { canonicalPathForArtifactComparison, isTerminalArtifactHardLinked, truncateMobileFilePreview -} from './runtime-terminal-artifact-integrity' +} from './artifact-integrity' import { resolveAllowedLocalTerminalArtifactPath, openLocalTerminalArtifactGrant, readLocalTerminalArtifactFileFromHandle, readLocalTerminalArtifactPreviewFromHandle -} from './runtime-file-commands-terminal-file-paths' -import { statLocalTerminalArtifact } from './runtime-terminal-artifact-stat' -import { requireReachableFilesystemRoute } from '../providers/execution-host-provider-dispatch' -import { getConnectionExecutionHostId } from '../../shared/execution-host' -import { assertPreviewWithinTransportBudget } from './runtime-file-commands-mobile-file-list-limit' -import { SshHostNotServedError } from '../providers/ssh-host-not-served-error' -import { isMobileBinaryPath } from './runtime-file-command-host' -import { writeTerminalArtifactFile } from './runtime-terminal-artifact-write' +} from '../../runtime-file-commands-terminal-file-paths' +import { statLocalTerminalArtifact } from './artifact-stat' +import { requireReachableFilesystemRoute } from '../../../providers/execution-host-provider-dispatch' +import { getConnectionExecutionHostId } from '../../../../shared/execution-host' +import { assertPreviewWithinTransportBudget } from '../../runtime-file-commands-mobile-file-list-limit' +import { SshHostNotServedError } from '../../../providers/ssh-host-not-served-error' +import { isMobileBinaryPath } from '../../runtime-file-command-host' +import { writeTerminalArtifactFile } from './artifact-write' export class RuntimeTerminalArtifacts { private readonly grants: RuntimeTerminalFileGrants