refactor(runtime): organize file search and terminal artifacts by domain (#27571)

This commit is contained in:
Neil
2026-10-14 01:01:37 -07:00
committed by GitHub
parent bbbeb96f4b
commit 230b39c279
28 changed files with 185 additions and 112 deletions
+2 -2
View File
@@ -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,
+109 -12
View File
@@ -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 <ref>: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
@@ -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 }
@@ -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(() => {
@@ -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<ResolvedRuntimeFileTarget['worktree'], 'id' | 'path'>
@@ -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
@@ -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', () => {
@@ -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[]
+2 -2
View File
@@ -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'
@@ -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'
@@ -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
@@ -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'
@@ -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
@@ -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'
@@ -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(
@@ -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'
@@ -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 {
@@ -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(
@@ -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'
@@ -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[],
@@ -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()),
@@ -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<string[]> {
const roots = new Set<string>([tmpdir()])
@@ -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<{
@@ -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<RuntimeTerminalFileGrants, 'requireTerminalFileGrant' | 'refreshTerminalFileGrant'>,
@@ -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
@@ -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
@@ -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