Skip to content

refactor(runtime): collapse redundant tool call argument views - #4971

Merged
me2seeks merged 4 commits into
apache:mainfrom
testikun:codex/issue-4908-call-data-v2
Sep 16, 2026
Merged

me2seeks merged 4 commits into
apache:mainfrom
testikun:codex/issue-4908-call-data-v2

Conversation

@testikun

@testikun testikun commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Refs #4908
Refs #4909

Summary

  • Keep tool-call argument preparation in ToolRuntime, its single lifecycle owner.
  • Snapshot provider input directly as executionArgs instead of creating and returning a second alias.
  • Keep the permission projection distinct for policy/UI use.
  • Use one persistedArgs value for both durable recording and model replay, removing the always-identical modelFacingArgs pass-through.
  • Remove the proposed tool-call-snapshot.ts module, its input/output interfaces, and its admission-state booleans.

This revises the scope in response to review. The previous extraction made one file shorter but increased repository-wide concepts and maintenance points. The current diff instead removes one redundant representation and one drift point without adding a layer.

Behavior preserved

  • Input snapshotting still occurs synchronously before the first await.
  • Declared schema validation and direct-only/sandbox-boundary exceptions keep their existing order.
  • Permission projections remain isolated from execution arguments.
  • Computer Use still writes the bounded tool-dialect privacy projection to durable history and model replay.
  • Admission, T1/T2, execution, telemetry, artifacts, and publication remain owned by ToolRuntime.

Measurements

Relative to current main (4410c3a2d):

  • one changed file: packages/runtime/src/tool-runtime.ts
  • +8/-42 (net -34 production lines)
  • tool-runtime.ts: 3,600 -> 3,566 lines
  • no new module, interface, or public API

Verification

Using Node 24.20.0:

  • clean npm ci with repository dependency patches applied and 0 audit vulnerabilities
  • npm run build:test
  • full workspace typecheck
  • repository lint and Biome format check
  • focused ToolRuntime/Computer Use/model-history/CodeMode suites: 73/73
  • full Runtime suite: 3,363 passed, 14 skipped, 0 failed
  • git diff --check upstream/main...HEAD

AI use

OpenAI Codex performed the synchronization, scope revision, implementation, and local verification. The contributor remains responsible for review and submission.

@testikun
testikun force-pushed the codex/issue-4908-call-data-v2 branch 2 times, most recently from 4a6b357 to ef9da46 Compare September 7, 2026 09:37
@github-actions github-actions Bot added the effort/L Under 1000 readable lines label Sep 7, 2026
@testikun
testikun force-pushed the codex/issue-4908-call-data-v2 branch 2 times, most recently from 66f2b36 to 36feaa7 Compare September 7, 2026 09:52
@testikun

testikun commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Why this extraction exists

This change is not intended to create four independently transformed or redacted copies of every tool argument. The four names describe different consumers of the same call data:

  • executionArgs: the stable snapshot used by the implementation or managed transform;
  • permissionArgs: the projection used by permission and policy logic;
  • persistedArgs: the call shape recorded in RuntimeEvent/durable data;
  • modelFacingArgs: the call shape replayed to the model, currently identical to persistedArgs.

For ordinary tools these values may be identical. They diverge when a tool has a permission projection, and Computer Use additionally applies its existing privacy and accepted-field-name projection before persistence/model replay.

The extraction gives that existing relationship one internal owner. Previously it lived inline in executeTool(), alongside admission, client preparation, managed mutation, T1/T2, execution and publication. Because every view is typed as unknown, using the wrong view would normally compile and surface later as a permission, replay or privacy regression. tool-call-snapshot.ts owns only snapshot/validation/projection construction; it does not own admission, dispatch identity, durability, transcript publication or execution.

A separate module is used because this is a pure data boundary with no ToolRuntime state. Keeping the helpers in the 4,197-line lifecycle module would shorten executeTool() but leave the rule without an independently readable and testable owner. The boundary remains deliberately small: no full call object, no runId/operationId, no service classes, and no common-field abstraction.

This is also intentionally independent of #4879. It does not change appendMessage, ToolCallMessage, ToolResultMessage, RuntimeEvent schemas or the transcript path. #4879 may remove one consumer, but RuntimeEvent, durable preparation and model replay still need the same argument views.

Measured production change: tool-runtime.ts 4,197 -> 4,086 lines, plus a 172-line internal module, for a temporary net +61 production lines. The extraction is not presented as net deletion. Test changes are kept on the real settleToolCall() entry point; the new async case proves the provider input is snapshotted before schema validation yields, and it fails if the entry snapshot is removed.

@testikun

testikun commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

@Astro-Han could you please review this specifically against the direction of #4879?

The intended boundary is entirely before transcript publication: it extracts the existing argument snapshot, declared validation, permission projection and persisted/model-facing projection, while leaving appendMessage, call/result messages, RuntimeEvent construction and T1/T2 unchanged. The main question is whether this remains a clean precursor to #4879, or whether any part of the argument-view ownership should wait for the RuntimeEvent-only transcript cutover.

@testikun
testikun force-pushed the codex/issue-4908-call-data-v2 branch from 36feaa7 to 1f2cecd Compare September 8, 2026 03:01
@github-actions github-actions Bot added effort/M Under 500 readable lines and removed effort/L Under 1000 readable lines labels Sep 8, 2026
Merge main with RuntimeEvent-only transcript support. Remove unused exports and intermediate aliases while retaining the distinct argument roles.

Generated-by: OpenAI Codex
@testikun

Copy link
Copy Markdown
Contributor Author

Automated follow-up by OpenAI Codex on behalf of testikun (not an independent human review). Merged main containing #4879; the RuntimeEvent-only transcript dependency is no longer pending. Full build:test, full typecheck and lint pass. 95 focused ToolRuntime/SQLite/model-history tests pass; full Runtime suite: 3,349 passed, 13 skipped, 0 failed. Simplification retained after verification: removed unused exported implementation types/helper and redundant intermediate aliases. Admission, persistence and lifecycle ownership remain in ToolRuntime. Please review the latest head.

Astro-Han

This comment was marked as duplicate.

@Astro-Han
Astro-Han dismissed their stale review September 12, 2026 15:20

Withdrawing my approval pending the overall simplification assessment explained in the follow-up review. Behavior preservation alone does not establish the value of this extraction.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining the boundary and doing the verification. I want to correct my earlier approval: I checked behavior preservation, but gave too much weight to making tool-runtime.ts smaller and not enough to whether the repository becomes simpler overall. That was my mistake.

For this refactor, I would like the acceptance criterion to be a reduction in overall complexity: fewer duplicated rules, concepts, intermediate representations, layers, and maintenance points. Moving an already centralized implementation into another file and adding input/output interfaces does not, by itself, meet that goal. Line count is a useful signal, not the sole criterion, but the current net growth needs a concrete simplification benefit beyond a smaller source file.

I am comfortable with a larger PR or a broader refactor if it removes the underlying complexity coherently. I would prefer that over a small extraction that leaves the same responsibilities in place and adds another interface to maintain. This is not a request to split the work into more wrappers or facade layers.

Could you revisit the scope with that goal? Start from the smallest complete argument-processing path, remove unnecessary pass-through fields and redundant representations where the actual consumers allow it, and show which rules or maintenance points disappear. Keep the execution/permission/privacy contracts and the existing regression coverage. If the extraction cannot demonstrate that tradeoff, keeping the logic in place is a reasonable outcome too.

I am withdrawing my approval for a87f1b263 while that design question is revisited. The earlier behavior checks still stand; this is a correction to my assessment of the refactor's value, not a newly discovered runtime defect. Thanks for taking another look.

中文

我想纠正之前的批准:我确认了行为保持,但过于看重单个文件缩短,没有充分判断仓库整体是否更简单,这是我的判断失误。

我希望重构减少重复规则、概念、中间表示、层级和维护点。可以接受更大规模的 PR 和重构,只要它连贯地消除原有复杂度;不能仅把已有集中逻辑搬走,再增加输入输出接口。行数不是唯一指标,但净增长必须换来具体收益。

请按这个目标重新考虑范围,保留执行、权限和隐私契约,删去没有必要的透传和重复表示,说明最终消除了哪些维护点。如果抽取本身无法带来这样的收益,保留原地实现也可以。我会撤回当前批准,待设计取舍重新收敛后复审;这不是新发现的运行时缺陷。

@testikun testikun changed the title refactor(runtime): extract tool call argument boundary refactor(runtime): collapse redundant tool call argument views Sep 16, 2026

@me2seeks me2seeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 8802b8454fb3cf12c3303caae3a5e8f72538bff0. This revision removes the earlier extraction layer and now makes a small behavior-preserving simplification: the two removed aliases were definitionally identical to their surviving values, while synchronous input snapshotting, schema validation, permission projection, Computer Use privacy projection, admission, durability, and replay boundaries remain unchanged. Exact-head test is green, the PR is mergeable, and there are no review threads.

@me2seeks
me2seeks merged commit fe79d00 into apache:main Sep 16, 2026
1 check passed

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at 8802b84. The revised scope is the right call — collapsing modelFacingArgs into persistedArgs removes a dead alias instead of adding a layer, and the snapshot/clone semantics are unchanged (structuredClone(input.persistedArgs) is the same value the removed field carried). The remaining modelFacingArgs in computer-use-tools.ts is a separate debug-record field, not a dangling reference. Clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants