mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 02:44:50 +01:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The adapter utilities provide sandbox transport paths for agent execution > - The retired `duplex_v1` path remains in host, gateway, and test code after `http2_v1` replaced it > - Retired transport code adds maintenance cost and leaves an unsafe fallback for unknown gateway modes > - This pull request removes the retired path, moves shared `http2_v1` contracts to a leaf module, and closes mode dispatch to a fixed allowlist > - The benefit is a smaller transport surface and explicit failure for unsupported modes ## Linked Issues or Issue Description Refs #12120 The `http2_v1` transport replaced `duplex_v1`, but the retired broker, gateway, constants, and tests remain in the adapter utilities. An unknown bridge mode can also fall through to the queue gateway when a queue directory exists. This change removes the retired code and rejects unsupported modes before gateway selection. ## What Changed - Delete the host `duplex_v1` broker and its transport-only tests. - Delete the in-sandbox duplex gateway and retired mode constants. - Move shared `http2_v1` symbols into `bridge-transport-contract.ts`. - Update the remaining importers and repair their focused tests. - Validate bridge modes against `http2_v1` and `queue_v1` before queue lookup. - Keep `queue_v1`, `duplex-frame-codec.ts`, and duplex telemetry dimensions unchanged. ## Verification - [x] `npx tsc --noEmit -p packages/adapter-utils` passes. - [x] `npx vitest run packages/adapter-utils/src` passes: 48 files and 968 tests pass, with 4 pre-existing platform skips. - [x] Full CI is green on this pull request. - [x] Greptile review is complete and every finding is resolved. ## Risks The change removes an internal transport that no host path selects. The main risk is an overlooked import or test dependency. Targeted typecheck and tests cover the adapter utility package. Full CI must confirm workspace-wide compatibility. ## Model Used Anthropic Claude Sonnet 5 assisted with the implementation, as recorded in the commit. The commit does not record a context-window size or reasoning mode. ## 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 `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) 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>
62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
/**
|
|
* Shared contract for the sandbox callback bridge transports.
|
|
*
|
|
* The retired duplex_v1 broker first defined these symbols. The host
|
|
* broker is gone, but the http2_v1 transport and the ACPX engine
|
|
* run-disposition seam still use them. This leaf module holds the
|
|
* survivors, so a caller of the run-disposition seam does not import the
|
|
* whole HTTP/2 bridge server module graph to reach one error code.
|
|
*/
|
|
|
|
import type { DuplexLossReason } from "./duplex-observability.js";
|
|
|
|
/**
|
|
* The typed error code the host reports when the bridge control channel
|
|
* died before an orderly completion. Both the ACP lane and the CLI lane
|
|
* report this one code, so the run disposition is identical across the two
|
|
* lanes.
|
|
*/
|
|
export const DUPLEX_CHANNEL_LOST_ERROR_CODE = "duplex_channel_lost";
|
|
|
|
/**
|
|
* The terminal run disposition a bridge transport computes from its ordered
|
|
* lifecycle. A `failed` disposition means a terminal loss ordered before an
|
|
* orderly completion, so the run must not report success. The typed loss
|
|
* reason names the cause; it is `null` for a success.
|
|
*/
|
|
export interface DuplexBrokerRunDisposition {
|
|
/** True when a terminal loss ordered before an orderly completion. */
|
|
failed: boolean;
|
|
/** The typed, closed loss reason on a failure; `null` on a success. */
|
|
lossReason: DuplexLossReason | null;
|
|
}
|
|
|
|
/** The nested timeout budgets. Each inner budget is smaller than its outer budget. */
|
|
export interface DuplexBrokerBudgets {
|
|
/** The deadline for one forward call, in milliseconds. */
|
|
forwardTimeoutMs: number;
|
|
/** The deadline for the broker to send one response frame, in milliseconds. */
|
|
responseBudgetMs: number;
|
|
/** The deadline the in-sandbox gateway waits for the response frame, in milliseconds. */
|
|
gatewayWaitMs: number;
|
|
}
|
|
|
|
/** The default nested budgets: forward 30 s, response 32 s, gateway wait 35 s. */
|
|
export const DEFAULT_DUPLEX_BROKER_BUDGETS: DuplexBrokerBudgets = {
|
|
forwardTimeoutMs: 30_000,
|
|
responseBudgetMs: 32_000,
|
|
gatewayWaitMs: 35_000,
|
|
};
|
|
|
|
/**
|
|
* The safe HTTP methods. RFC 7231 section 4.2.1 defines this set. A safe method
|
|
* does not change host state, so the host applies no mutation for it. A caller
|
|
* can retry a safe method after a forward failure without a double-apply risk.
|
|
*/
|
|
const SAFE_BRIDGE_METHODS = new Set(["GET", "HEAD", "OPTIONS", "TRACE"]);
|
|
|
|
/** Report whether the method is safe, so a forward failure stays retryable. */
|
|
export function isSafeBridgeMethod(method: string): boolean {
|
|
return SAFE_BRIDGE_METHODS.has(method.trim().toUpperCase());
|
|
}
|