mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-21 00:05:49 +02:00
## Thinking Path > - Paperclip runs AI agents through adapters and sandboxed execution targets. > - Duplex routes retain bytes across route data, broker messages, decoder buffers, and readiness replay. > - Per-route limits bound each route but do not bound the total retained bytes across many routes. > - A process-owned ledger must charge each retained buffer before allocation and release the charge during cleanup. > - This pull request adds the aggregate ledger, connects it to host and sandbox duplex paths, and adds route coverage. > - The benefit is a fail-closed process-wide byte limit that keeps concurrent duplex work within a safe resource budget. ## Linked Issues or Issue Description **Subsystem affected** This change affects packages/adapter-utils and server duplex orchestration. **Problem or motivation** Many routes can each stay below their per-route limits while their combined retained bytes exceed a safe process budget. **Proposed solution** Add a process-owned aggregate byte ledger. Charge route data, broker bytes, decoder buffers, and readiness replay bytes before allocation. Release each charge during cleanup. Use a separate sandbox_process decoder cap for the in-sandbox path. **Alternatives considered** Keep only per-route limits. This does not bound the combined process use. Set a fixed limit at one call site. This misses retained bytes in other duplex paths. **Roadmap alignment** This is a tightly scoped reliability and resource-safety improvement. It does not duplicate a roadmap feature. **Additional context** The aggregate ceiling uses a safe 256 MiB default. An invalid override falls back to that default and reports the rejected value. ## What Changed - Add a process-owned aggregate byte ledger for duplex route resource use. - Charge and release route data, broker forward and response bytes, decoder buffers, and readiness replay bytes. - Bound host-to-worker pending writes and standard input transport bytes. - Add a separate decoder cap for the sandbox_process path. - Make invalid aggregate-ceiling overrides fall back to the safe default without host startup failure. - Add adapter-utils and server tests for charging, release, rejection, cleanup, and many-route aggregate limits. ## Verification - pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit - pnpm --filter @paperclipai/server exec tsc --noEmit - Run the focused adapter-utils duplex ledger and execution-target tests. - Run the server aggregate-ledger route test. - Confirm all required pull request checks pass on this branch. ## Risks The ledger touches several duplex buffer paths. A missed release could reduce later capacity until process restart. The tests cover charge, release, rejection, cleanup, and route aggregation. The change uses a safe default when configuration input is invalid. ## Model Used OpenAI GPT-5 Codex. The runtime model ID and context window are not exposed to this task. The model used tool calls, shell commands, and code review workflow support. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with Fixes/Closes/Refs OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub issue references) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
33 lines
1.5 KiB
TypeScript
33 lines
1.5 KiB
TypeScript
import {
|
|
resolveDuplexAggregateCeilingBytes,
|
|
type DuplexAggregateCeilingOverrideRejectionReporter,
|
|
} from "@paperclipai/adapter-utils/duplex-aggregate-byte-ledger";
|
|
|
|
/**
|
|
* Resolve the aggregate duplex route byte ceiling from the raw operator override
|
|
* string. The host reads the override from
|
|
* PAPERCLIP_MAX_AGGREGATE_DUPLEX_ROUTE_BYTES.
|
|
*
|
|
* This helper distinguishes an absent variable from a present blank value. An
|
|
* absent variable is `undefined`. The helper then uses the documented default and
|
|
* does not report a rejection. A present variable is a string, even when the
|
|
* string holds only whitespace. The helper sends every present string through
|
|
* `Number`, so a blank or whitespace-only value becomes `0`. The numeric
|
|
* validation in {@link resolveDuplexAggregateCeilingBytes} rejects `0`, reports it
|
|
* through `onRejectedOverride`, and returns the safe default. So a present blank
|
|
* value is visible as invalid instead of silent as absent.
|
|
*
|
|
* `Number` ignores surrounding whitespace, so a valid value with surrounding
|
|
* spaces still parses. The reporter receives only the parsed number, never the raw
|
|
* string, so no operator-supplied text reaches a log line.
|
|
*/
|
|
export function resolveDuplexAggregateCeilingBytesFromEnv(
|
|
rawOverride: string | undefined,
|
|
onRejectedOverride?: DuplexAggregateCeilingOverrideRejectionReporter,
|
|
): number {
|
|
return resolveDuplexAggregateCeilingBytes(
|
|
rawOverride === undefined ? undefined : Number(rawOverride),
|
|
onRejectedOverride,
|
|
);
|
|
}
|