mirror of
https://github.com/stablyai/orca.git
synced 2026-10-28 08:02:54 +00:00
refactor(memory-safety): group the shared bounding primitives into one folder
The six primitives that exist to stop unbounded memory growth were scattered through `src/shared/` next to unrelated modules, so there was nowhere to state when a new ceiling is warranted — and the last attempt at this work added many that were not. Moves them under `src/shared/memory-safety/` and adds a README carrying the doctrine: bound at ingress, not in the interior; set limits far above real use; decide overload behavior explicitly; and prefer fixing measured growth over adding a speculative ceiling. No behavior change. Pure move plus import-path updates across 48 files, with `git mv` preserving history. Includes two `vi.mock` paths that had to move with their modules — a mock left on the old path silently stops applying, which the suite caught. Verified: typecheck clean, oxlint 0 errors, 18,668 tests passing across src/shared and src/main.
This commit is contained in:
@@ -2,7 +2,7 @@ import { mkdtempSync, rmSync, truncateSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { NodeFileReadTooLargeError } from '../shared/node-bounded-file-reader'
|
||||
import { NodeFileReadTooLargeError } from '../shared/memory-safety/node-bounded-file-reader'
|
||||
import {
|
||||
MAX_AGENT_STATE_FILE_BYTES,
|
||||
MAX_AGENT_STATE_JSON_NESTING_DEPTH,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { readNodeFileSyncWithinLimit } from '../shared/node-bounded-file-reader'
|
||||
import { assertJsonTextStructureWithinLimits } from '../shared/json-text-structure-limit'
|
||||
import { readNodeFileSyncWithinLimit } from '../shared/memory-safety/node-bounded-file-reader'
|
||||
import { assertJsonTextStructureWithinLimits } from '../shared/memory-safety/json-text-structure-limit'
|
||||
|
||||
export const MAX_AGENT_STATE_FILE_BYTES = 4 * 1024 * 1024
|
||||
export const MAX_AGENT_STATE_JSON_STRUCTURAL_TOKENS = 1_000_000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
readNodeFileSyncWithinLimit,
|
||||
readNodeFileWithinLimit
|
||||
} from '../../shared/node-bounded-file-reader'
|
||||
} from '../../shared/memory-safety/node-bounded-file-reader'
|
||||
|
||||
export function readTerminalHistoryBuffer(filePath: string, maxBytes: number): Buffer {
|
||||
return readNodeFileSyncWithinLimit(filePath, maxBytes).buffer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable max-lines -- Why: git status/discard/chunking behavior is verified together here to keep the command contract readable in one place. */
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type * as NodeFs from 'node:fs'
|
||||
import type * as BoundedFileReader from '../../shared/node-bounded-file-reader'
|
||||
import type * as BoundedFileReader from '../../shared/memory-safety/node-bounded-file-reader'
|
||||
import path from 'node:path'
|
||||
import {
|
||||
MAX_RENDERED_DIFF_COMBINED_CHARACTERS,
|
||||
@@ -63,7 +63,7 @@ vi.mock('fs', () => ({
|
||||
existsSync: existsSyncMock
|
||||
}))
|
||||
|
||||
vi.mock('../../shared/node-bounded-file-reader', async (importOriginal) => {
|
||||
vi.mock('../../shared/memory-safety/node-bounded-file-reader', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof BoundedFileReader>()
|
||||
return {
|
||||
...actual,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { clampUtf8TextTail } from '../../../../shared/utf8-byte-limits'
|
||||
import { clampUtf8TextTail } from '../../../../shared/memory-safety/utf8-byte-limits'
|
||||
|
||||
export type EagerBufferChunk = {
|
||||
data: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { TERMINAL_SCROLLBACK_SESSION_BUFFER_BYTE_LIMIT } from '../../../../shared/terminal-scrollback-limits'
|
||||
import type { TerminalLayoutSnapshot } from '../../../../shared/types'
|
||||
import { getUtf8ByteLength } from '../../../../shared/utf8-byte-limits'
|
||||
import { getUtf8ByteLength } from '../../../../shared/memory-safety/utf8-byte-limits'
|
||||
|
||||
const LEAF_ID = '11111111-1111-4111-8111-111111111111' as const
|
||||
const LEAF_ID_2 = '22222222-2222-4222-8222-222222222222' as const
|
||||
|
||||
@@ -7,7 +7,7 @@ import { mergeCapturedLeafState } from './merge-captured-leaf-state'
|
||||
import { resolveTerminalLayoutActiveLeafId } from './terminal-layout-leaf-ids'
|
||||
import { TERMINAL_SCROLLBACK_SESSION_BUFFER_BYTE_LIMIT } from '../../../../shared/terminal-scrollback-limits'
|
||||
import { serializeWithAbsoluteCursor } from '../../../../shared/terminal-serialize-absolute-cursor'
|
||||
import { measureUtf8ByteLength } from '../../../../shared/utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from '../../../../shared/memory-safety/utf8-byte-limits'
|
||||
|
||||
const MAX_BUFFER_BYTES = TERMINAL_SCROLLBACK_SESSION_BUFFER_BYTE_LIMIT
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ import {
|
||||
resolveGrokSessionsDir
|
||||
} from './grok-session-paths'
|
||||
import { sweepStaleAgentHookEndpointTemps } from './agent-hook-endpoint-temp-cleanup'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
/** Maximum request body size accepted by the listener (1 MB). */
|
||||
export const HOOK_REQUEST_MAX_BYTES = 1_000_000
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
normalizeOptionalMultilineField,
|
||||
normalizePromptField
|
||||
} from './agent-status-field-normalization'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export { AGENT_STATUS_MAX_FIELD_LENGTH } from './agent-status-field-normalization'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
const BROWSER_SCREENCAST_KIND = 0x62
|
||||
const BROWSER_SCREENCAST_VERSION = 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { TuiAgent } from './types'
|
||||
import { isTuiAgentEnabled } from './tui-agent-selection'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
/* eslint-disable max-lines -- Why: this is the single registry for non-interactive commit-message agents, their model discovery parsers, and UI capabilities. */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
MAX_SSH_RELAY_GRACE_PERIOD_SECONDS,
|
||||
MIN_SSH_RELAY_GRACE_PERIOD_SECONDS
|
||||
} from './ssh-types'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
// Why: ephemeral-vm-recipe-doctor imports Node's fs/path, so it must NOT be
|
||||
// re-exported through this barrel — the renderer/web-client imports this module
|
||||
// and would otherwise pull Node built-ins into the browser bundle (build fails).
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { existsSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { JsonStringifyByteLimitError } from './node-bounded-json-stringify'
|
||||
import { readNodeFileSyncWithinLimit } from './node-bounded-file-reader'
|
||||
import { writeSecureJsonFileWithinLimit } from './bounded-secure-json-file'
|
||||
import { JsonStringifyByteLimitError } from './memory-safety/node-bounded-json-stringify'
|
||||
import { readNodeFileSyncWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
import { writeSecureJsonFileWithinLimit } from './memory-safety/bounded-secure-json-file'
|
||||
import { hardenExistingSecureFile } from './secure-file'
|
||||
import {
|
||||
EphemeralVmRuntimeRecordSchema,
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { NodeFileReadTooLargeError, readNodeFileWithinLimit } from './node-bounded-file-reader'
|
||||
import {
|
||||
NodeFileReadTooLargeError,
|
||||
readNodeFileWithinLimit
|
||||
} from './memory-safety/node-bounded-file-reader'
|
||||
import {
|
||||
assertJsonTextStructureWithinLimits,
|
||||
type JsonTextStructureLimits
|
||||
} from './json-text-structure-limit'
|
||||
} from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const EXTERNAL_AUTOMATION_JOBS_FILE_MAX_BYTES = 8 * 1024 * 1024
|
||||
export const EXTERNAL_AUTOMATION_JOBS_MAX_ENTRIES = 10_000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
assertJsonTextStructureWithinLimits,
|
||||
type JsonTextStructureLimits
|
||||
} from './json-text-structure-limit'
|
||||
} from './memory-safety/json-text-structure-limit'
|
||||
|
||||
const INITIAL_RESPONSE_CAPACITY_BYTES = 64 * 1024
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ const { lstatMock, readFileMock } = vi.hoisted(() => ({
|
||||
|
||||
vi.mock('fs/promises', () => ({ lstat: lstatMock }))
|
||||
|
||||
vi.mock('./node-bounded-file-reader', () => ({
|
||||
vi.mock('./memory-safety/node-bounded-file-reader', () => ({
|
||||
readNodeFileWithinLimit: async (path: string) => ({
|
||||
buffer: await readFileMock(path),
|
||||
stats: mockFileStat(0)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isBinaryBuffer } from './binary-buffer'
|
||||
import { decodeGitCQuotedPath } from './git-cquoted-path'
|
||||
import { DEFAULT_GIT_STATUS_LIMIT } from './git-status-limit'
|
||||
import { iterateNulDelimitedFields } from './nul-delimited-fields'
|
||||
import { readNodeFileWithinLimit } from './node-bounded-file-reader'
|
||||
import { readNodeFileWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
|
||||
export type GitLineStats = { added?: number; removed?: number }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const HTML_TO_PDF_MAX_INPUT_BYTES = 32 * 1024 * 1024
|
||||
export const HTML_TO_PDF_MEMORY_LIMIT_ERROR = 'HTML export exceeds the PDF memory limit'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readNodeFileWithinLimit } from './node-bounded-file-reader'
|
||||
import { readNodeFileWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
|
||||
export const LINUX_PROC_NETWORK_TABLE_MAX_BYTES = 8 * 1024 * 1024
|
||||
export const LINUX_PROC_LISTENING_SOCKET_MAX_ENTRIES = 2_048
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { MarkdownDocument } from './types'
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const MARKDOWN_DOCUMENT_LISTING_MAX_DOCUMENTS = 20_000
|
||||
export const MARKDOWN_DOCUMENT_LISTING_MAX_METADATA_BYTES = 8 * 1024 * 1024
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const MCP_CONFIG_INSPECTION_MAX_BYTES = 256 * 1024
|
||||
export const MCP_CONFIG_INSPECTION_MAX_CODE_UNITS = 256 * 1024
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Memory safety
|
||||
|
||||
Shared primitives that stop unbounded memory growth. Renderer OOM is Orca's dominant crash class
|
||||
(#9984): heap climbs to V8's ~3.5 GB ceiling and the process is killed. The reported reproduction
|
||||
(#9872) was a single unbounded `Map` that also spread-copied itself on every update.
|
||||
|
||||
**Read this before adding a new limit, and before writing code that reads or accumulates data.**
|
||||
|
||||
## The rule: bound at ingress, not in the interior
|
||||
|
||||
Put a ceiling where untrusted or unpredictably-large data first enters memory:
|
||||
|
||||
- **Files** — anything read from disk, a repo, or a remote host
|
||||
- **Transport** — IPC, WebSocket frames, relay/SSH payloads, subprocess output
|
||||
- **Parsing** — JSON/YAML/CSV/notebook text, base64, image headers
|
||||
- **Enumeration** — directory walks, provider pagination, session scans
|
||||
- **Long-lived accumulators** — caches and maps keyed by something a user can grow without limit
|
||||
(pane IDs, session IDs, paths) that live for the process lifetime
|
||||
|
||||
Do **not** add ceilings to interior data structures whose size is already implied by a bounded
|
||||
input. A second ceiling behind an existing one is not defense in depth; it is a second thing that
|
||||
can be wrong, and every ceiling is a new user-visible failure mode when it is hit.
|
||||
|
||||
If you cannot name the untrusted input and the bound it crosses, you do not need a limit.
|
||||
|
||||
### Never copy an accumulator on every update
|
||||
|
||||
The crash that started this (#9872) was not only an unbounded `Map` — it also rebuilt itself on every
|
||||
status ping (`state = { ...state, [key]: value }`). Copy-per-update turns a large collection into
|
||||
repeated large allocations, so it reaches the heap ceiling far sooner than its size suggests. Mutate
|
||||
in place, or use `BoundedMap`. No lint rule catches this; it is on you to notice.
|
||||
|
||||
## What's here
|
||||
|
||||
| Module | Use it for |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `bounded-map.ts` | A cache/map that must not grow forever. Count and/or byte ceiling with LRU eviction. |
|
||||
| `node-bounded-file-reader.ts` | Reading a file whose size you do not control. Checks before allocating and while growing. |
|
||||
| `node-bounded-json-stringify.ts` | Serializing to JSON when the result could be huge. |
|
||||
| `bounded-secure-json-file.ts` | Writing a secret-bearing JSON file within a byte ceiling. |
|
||||
| `json-text-structure-limit.ts` | Guarding `JSON.parse` against depth/token amplification before it runs. |
|
||||
| `utf8-byte-limits.ts` | Measuring/truncating UTF-8 without materializing the whole string. |
|
||||
|
||||
Domain-specific ceilings (e.g. `git-status-limit.ts`, `terminal-scrollback-limits.ts`) live next to
|
||||
the code they bound, not here. This folder is only for primitives reused across domains.
|
||||
|
||||
## Rules for a new ceiling
|
||||
|
||||
1. **Set it far above real use.** A limit a normal user reaches is a bug. Ordinary large repos, long
|
||||
terminal sessions, and big diffs must pass untouched. State the headroom in a comment.
|
||||
2. **Fail closed, and never crash a remote host.** An unmeasurable size rejects the item; it must not
|
||||
poison a ledger or throw into a relay running on someone else's machine.
|
||||
3. **Decide overload behavior explicitly** — reject, evict, or truncate — and document which.
|
||||
Silent truncation of user data is the worst option; prefer a visible, recoverable failure.
|
||||
4. **Release on every exit path**, including throw, abort, disconnect, and renderer teardown. Pair
|
||||
acquisition with `try`/`finally`; do not rely on the happy path.
|
||||
5. **Test the exact boundary and boundary+1**, through every entry point — including hydration,
|
||||
restore, and replay paths, not just the create path.
|
||||
|
||||
## Enforcement
|
||||
|
||||
None of this is lint-enforced today: `readFile`, `JSON.parse`/`stringify`, unbounded `fetch` body
|
||||
reads, `createReadStream`, `readdir`, recursion depth, copy-per-update amplification, and
|
||||
accumulator growth are all caught by review, not tooling. The rules above are the standard a
|
||||
reviewer should hold you to.
|
||||
|
||||
## Before you add one
|
||||
|
||||
Prefer fixing the actual growth. The real crash was fixed by capping one map that was already known
|
||||
to grow, found via the heap-highwater breadcrumbs in `renderer_memory_highwater` (#9984). Measure
|
||||
first: if you cannot point at evidence that something grows, a new ceiling is speculation, and
|
||||
speculation here costs review burden, user-visible failure modes, and code that outlives its reason.
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { stringifyJsonWithinByteLimit } from './node-bounded-json-stringify'
|
||||
import { writeSecureFile } from './secure-file'
|
||||
import { writeSecureFile } from '../secure-file'
|
||||
|
||||
export function writeSecureJsonFileWithinLimit(
|
||||
targetPath: string,
|
||||
@@ -2,7 +2,10 @@ import { closeSync, ftruncateSync, mkdtempSync, openSync, rmSync, writeFileSync
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { NodeFileReadTooLargeError, readNodeFileSyncWithinLimit } from './node-bounded-file-reader'
|
||||
import {
|
||||
NodeFileReadTooLargeError,
|
||||
readNodeFileSyncWithinLimit
|
||||
} from './memory-safety/node-bounded-file-reader'
|
||||
|
||||
const tempDirectories: string[] = []
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const MAX_ORCA_YAML_BYTES = 256 * 1024
|
||||
export const MAX_ORCA_YAML_CODE_UNITS = 256 * 1024
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import { NodeFileReadTooLargeError } from './node-bounded-file-reader'
|
||||
import { JsonStringifyByteLimitError } from './node-bounded-json-stringify'
|
||||
import { NodeFileReadTooLargeError } from './memory-safety/node-bounded-file-reader'
|
||||
import { JsonStringifyByteLimitError } from './memory-safety/node-bounded-json-stringify'
|
||||
import {
|
||||
PersistedStateSecretCapacityError,
|
||||
assertPersistedStateSecretWithinLimit,
|
||||
|
||||
@@ -5,15 +5,15 @@ import {
|
||||
NodeFileReadTooLargeError,
|
||||
readNodeFileSyncWithinLimit,
|
||||
type BoundedNodeFileRead
|
||||
} from './node-bounded-file-reader'
|
||||
} from './memory-safety/node-bounded-file-reader'
|
||||
import {
|
||||
JsonStringifyByteLimitError,
|
||||
stringifyJsonWithinByteLimit
|
||||
} from './node-bounded-json-stringify'
|
||||
} from './memory-safety/node-bounded-json-stringify'
|
||||
import {
|
||||
assertJsonTextStructureWithinLimits,
|
||||
type JsonTextStructureLimits
|
||||
} from './json-text-structure-limit'
|
||||
} from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const ORCA_PERSISTED_STATE_MAX_BYTES = 64 * 1024 * 1024
|
||||
export const ORCA_PERSISTED_STATE_SECRET_MAX_BYTES = 4 * 1024 * 1024
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { truncateDiffForPrompt } from './commit-message-prompt'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const GENERATED_PULL_REQUEST_JSON_STRUCTURE_LIMITS = {
|
||||
structuralTokens: 64,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readNodeFileWithinLimit } from './node-bounded-file-reader'
|
||||
import { readNodeFileWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
import { getProcessOutputFields, iterateProcessOutputLines } from './process-output-field-scanner'
|
||||
|
||||
const GENERIC_LINUX_RIPGREP_INSTALL =
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const RELAY_JSON_MAX_STRUCTURAL_TOKENS = 1_000_000
|
||||
export const RELAY_JSON_MAX_NESTING_DEPTH = 128
|
||||
|
||||
@@ -2,7 +2,7 @@ import { mkdtempSync, rmSync, truncateSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { NodeFileReadTooLargeError } from './node-bounded-file-reader'
|
||||
import { NodeFileReadTooLargeError } from './memory-safety/node-bounded-file-reader'
|
||||
import { RELAY_VERSION_MARKER_MAX_BYTES, readRelayVersionMarkerSync } from './relay-version-marker'
|
||||
|
||||
const roots: string[] = []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readNodeFileSyncWithinLimit } from './node-bounded-file-reader'
|
||||
import { readNodeFileSyncWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
|
||||
export const RELAY_VERSION_MARKER_MAX_BYTES = 4 * 1024
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
JsonStringifyByteLimitError,
|
||||
stringifyJsonWithinByteLimit
|
||||
} from './node-bounded-json-stringify'
|
||||
} from './memory-safety/node-bounded-json-stringify'
|
||||
import { RemoteRuntimeClientError } from './remote-runtime-client-error'
|
||||
|
||||
export const REMOTE_RUNTIME_MAX_OUTBOUND_JSON_BYTES = 4 * 1024 * 1024
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
isKeepaliveFrame
|
||||
} from './runtime-rpc-envelope'
|
||||
import { RemoteRuntimeClientError } from './remote-runtime-client-error'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const REMOTE_RUNTIME_JSON_STRUCTURE_LIMITS = {
|
||||
structuralTokens: 256 * 1024,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { join } from 'node:path'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export type RuntimeTransportMetadata =
|
||||
| {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { JsonStringifyByteLimitError } from './node-bounded-json-stringify'
|
||||
import { readNodeFileSyncWithinLimit } from './node-bounded-file-reader'
|
||||
import { JsonStringifyByteLimitError } from './memory-safety/node-bounded-json-stringify'
|
||||
import { readNodeFileSyncWithinLimit } from './memory-safety/node-bounded-file-reader'
|
||||
import { parsePairingCode, type PairingOffer } from './pairing'
|
||||
import { writeSecureJsonFileWithinLimit } from './bounded-secure-json-file'
|
||||
import { writeSecureJsonFileWithinLimit } from './memory-safety/bounded-secure-json-file'
|
||||
import { hardenExistingSecureFile } from './secure-file'
|
||||
import {
|
||||
createEnvironmentFromPairingOffer,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { join } from 'node:path'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
export const SERVE_UPDATE_HANDOFF_PATH_ENV = 'ORCA_SERVE_UPDATE_HANDOFF_PATH'
|
||||
export const SERVE_UPDATE_HANDOFF_FILE = 'serve-update-handoff.json'
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
SETUP_SCRIPT_IMPORT_MAX_TOML_LINES,
|
||||
SETUP_SCRIPT_IMPORT_MAX_UNSUPPORTED_FIELDS
|
||||
} from './setup-script-import-limits'
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
const CODEX_ENVIRONMENT_PATH = '.codex/environments/environment.toml'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const SETUP_SCRIPT_IMPORT_FILE_MAX_BYTES = 256 * 1024
|
||||
export const SETUP_SCRIPT_IMPORT_MAX_CODE_UNITS = 256 * 1024
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { getUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { getUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
import {
|
||||
admitSshConnectionState,
|
||||
admitSshDetectedPorts,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { EnrichedDetectedPort, SshConnectionState, SshConnectionStatus } from './ssh-types'
|
||||
import { clampUtf8TextPrefix, measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { clampUtf8TextPrefix, measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
|
||||
export const SSH_RETAINED_IDENTIFIER_MAX_UTF8_BYTES = 1024
|
||||
export const SSH_CONNECTION_ERROR_MAX_UTF8_BYTES = 16 * 1024
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
|
||||
const TERMINAL_STREAM_KIND = 0x74
|
||||
const TERMINAL_STREAM_VERSION = 1
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Design doc: docs/design/share-text-search.md.
|
||||
*/
|
||||
import { posix, win32 } from 'node:path'
|
||||
import { assertJsonTextStructureWithinLimits } from './json-text-structure-limit'
|
||||
import { assertJsonTextStructureWithinLimits } from './memory-safety/json-text-structure-limit'
|
||||
import { normalizeSearchResult } from './search-match-count'
|
||||
import { escapeRegex } from './string-utils'
|
||||
import type { SearchFileResult, SearchMatch, SearchOptions, SearchResult } from './types'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import { FLOATING_TERMINAL_WORKTREE_ID } from './constants'
|
||||
import type { WorkspaceSessionState } from './types'
|
||||
import { TERMINAL_SCROLLBACK_SESSION_BUFFER_BYTE_LIMIT } from './terminal-scrollback-limits'
|
||||
import { getUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { getUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
import {
|
||||
pruneLocalTerminalScrollbackBuffers,
|
||||
shouldPreserveTerminalScrollbackBuffers
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Repo, WorkspaceSessionState } from './types'
|
||||
import { FLOATING_TERMINAL_WORKTREE_ID } from './constants'
|
||||
import { getRepoIdFromWorktreeId } from './worktree-id'
|
||||
import { TERMINAL_SCROLLBACK_SESSION_BUFFER_BYTE_LIMIT } from './terminal-scrollback-limits'
|
||||
import { clampUtf8TextTail, measureUtf8ByteLength } from './utf8-byte-limits'
|
||||
import { clampUtf8TextTail, measureUtf8ByteLength } from './memory-safety/utf8-byte-limits'
|
||||
import { parseExecutionHostId } from './execution-host'
|
||||
|
||||
export type RepoConnection = Pick<Repo, 'id' | 'connectionId' | 'executionHostId'>
|
||||
|
||||
Reference in New Issue
Block a user