Skip to content

chore: ratchet weak public API types - #304

Open
neubig wants to merge 8 commits into
mainfrom
feat/oss-6127-public-type-ratchet
Open

chore: ratchet weak public API types#304
neubig wants to merge 8 commits into
mainfrom
feat/oss-6127-public-type-ratchet

Conversation

@neubig

@neubig neubig commented Jul 27, 2026

Copy link
Copy Markdown
Member
  • A human has tested these changes.

Why

The client previously had no repository-wide guard against new or widened weak
public types. Important domain boundaries could silently degrade even when
generated Agent Server operations remained strong.

Fixes #300
Linear: OSS-6127

Summary

  • Scan the built declaration graph reachable from every public package entry
    point and check in a reviewed budget of existing unknown sites.
  • Fail CI when a weak site is added, widened, changed, or removed without
    permanently lowering the budget.
  • Replace all remaining reachable public any declarations with unknown,
    with runtime narrowing for remote full-state events.
  • Merge main (including the Agent Server 1.40.0 schema and the merged
    canonical MCP settings operations from feat: add canonical MCP settings operations #302/feat(events): mirror SDK event payloads #318) and refresh the weak-type
    budget for the events/types refactor.

Issue Number

#300 / OSS-6127

How to Test

  • npm run build
  • npm run test:public-type-budget
  • npm run check:public-type-budget
  • env -u AGENT_SERVER_URL npm run test:coverage — 18 suites, 304 tests
  • npm run check:agent-server-api — checked-in contract is current for 1.40.0
  • npm run test:agent-server-api-tooling
  • npm run test:endpoint-audit-tooling
  • npm run lint — 0 errors
  • npm run format:check — all files formatted

Live evidence refresh (2026-08-08, head 63acaf7 = final branch commit after "trigger CI")

Re-ran the full validation on the current head (Node v26.6.0):

  • npm ci -> OK.
  • npm run build -> tsc && copy-json-assets && rewrite-relative-imports OK.
  • npm run check:public-type-budget -> Public weak-type budget unchanged: 103 sites (0 any, 103 unknown).
  • npm run test:public-type-budget -> self-test passed.
  • env -u AGENT_SERVER_URL npm run test:coverage -> 18 suites, 304 tests passed (includes the remote-state and agent changes).
  • npm run lint -> 0 errors, 8 pre-existing warnings (unchanged).
  • npm run format:check -> all files Prettier-clean.

Live evidence (AGENT)

Merge conflict resolution against main was validated locally on commit
cbfeeff:

$ npm run build                     # tsc + asset copy: OK
$ npm run test:public-type-budget   # public-type-budget self-test passed
$ npm run check:public-type-budget  # Public weak-type budget unchanged: 103 sites (0 any, 103 unknown)
$ npm run check:agent-server-api    # Checked-in Agent Server contract is current (1.40.0 artifact)
$ env -u AGENT_SERVER_URL npm run test:coverage  # 18 suites, 304 tests passed
$ npm run lint                      # 0 errors, 8 pre-existing warnings
$ npm run format:check              # All matched files use Prettier code style!

The budget refresh mirrors main's events/types refactor (handwritten
interfaces became schema-derived type aliases): six stale interface: budget
tuples were removed and two type: tuples added at the current fingerprints.

Video/Screenshots

Not applicable: this adds public type and CI enforcement without changing the
Canvas UI.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

Depends on #302. Public domain contracts, generic transport internals, and
deliberately opaque Cloud proxy payloads have separate budget groups. Generated
Agent Server declarations remain governed by the SDK OpenAPI quality allowlist
and the pinned generated-file drift check.

@github-actions github-actions Bot added the type: chore Maintenance / chores label Jul 27, 2026
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Endpoint audit

⚠️ 7 actionable Agent Server contract divergence(s) · report-only

Contract: pinned release artifact

Category Count
Actionable client-only calls 0
Actionable server-only operations 7
Documented non-divergences 13
Agent Server contract operations 117
Audited handwritten client endpoints 119

Actionable client-only calls (0)

none

Actionable server-only operations (7)

  • GET /api/conversations/{}/events
  • GET /api/file/archive
  • GET /api/git/commits
  • GET /api/git/commits/{}/changes
  • GET /api/init
  • POST /api/conversations/{}/load_plugin
  • POST /api/init
Documented non-divergences (13)

Client calls intentionally absent from the filtered contract (11)

  • GET /
  • GET /alive
  • GET /health
  • GET /ready
  • GET /server_info

Reason: Operational Agent Server endpoints intentionally excluded from the filtered public release artifact.
Owner: OpenHands runtime maintainers

  • DELETE /api/meta-profiles/{}
  • GET /api/meta-profiles
  • GET /api/meta-profiles/{}
  • POST /api/meta-profiles/{}
  • POST /api/meta-profiles/{}/activate

Reason: Client-ahead API stacked on the pending Agent Server meta-profiles implementation.
Owner: OpenHands SDK maintainers
Tracking: OpenHands/software-agent-sdk#3744

  • POST /api/profiles/{}/validate

Reason: Client-ahead API stacked on the pending Agent Server pre-flight LLM validation endpoint.
Owner: OpenHands TypeScript client maintainers
Tracking: OpenHands/software-agent-sdk#4422

Server operations covered by an exposed browser URL (2)

  • GET /api/conversations/{}/workspace
  • GET /api/conversations/{}/workspace/{}

Reason: RemoteWorkspace.startWorkspaceSession exposes these authenticated URLs for browser iframe and file requests; they are not HttpClient method calls.
Owner: OpenHands TypeScript client maintainers

@neubig
neubig force-pushed the feat/oss-6123-canonical-mcp-settings branch from b7dc267 to dfe83a5 Compare July 28, 2026 18:42
Base automatically changed from feat/oss-6123-canonical-mcp-settings to main July 29, 2026 13:44
neubig and others added 2 commits August 2, 2026 17:13
…type-ratchet

Resolve merge conflicts against main:
- Adopt main's generated Agent Server schema (1.40.0) and the merged
  canonical MCP settings operations (endpoint-based create/patch/delete).
- Keep the PR's Canonical* type aliases and the public-type ratchet.
- Refresh config/public-type-budget.json for the events/types refactor
  (interface -> type aliases) merged from main.

Co-authored-by: openhands <[email protected]>
Co-authored-by: openhands <[email protected]>
@neubig
neubig marked this pull request as ready for review August 15, 2026 00:15
@neubig
neubig requested a review from all-hands-bot August 15, 2026 03:32
@all-hands-bot

Copy link
Copy Markdown
Contributor

🤖 OpenHands is reviewing this PR.

Head commit: 83f7eefb82a7477b19e62fca5d11d52de9aff661
View the conversation: https://oss-agent-canvas.ngrok.dev/conversations/ffaa676b-40fa-470f-a7b7-920cd2029fb3

This comment was posted by an AI agent (OpenHands).

@all-hands-bot all-hands-bot 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.

This review was created by an AI agent (OpenHands) on behalf of the repository maintainers.

Summary

This PR introduces a repository-wide weak-type ratchet over the built public declaration graph, replaces reachable public any with unknown, and adds runtime narrowing for remote full-state events. I reviewed the diff across all 11 files, the budget config, the checker script, and the remote-state runtime changes.

No material issues found. The change is well-structured and the type tightenings are correct.

Key observations

  • remote-state.ts runtime narrowing is a genuine improvement. The previous Object.assign(this.cachedState, event.value) silently coerced non-object primitives (e.g. a string value would spread its characters as numeric-key properties into the cache). The new isRecord guard throws a descriptive error before any mutation, leaving the cache intact. The AsyncLock.acquire finally block releases the lock on the throw, and the new test verifies post-throw cache integrity (getExecutionStatus still resolves). Correct.

  • normalizeFullState rewrite is type-safe. Replacing (info as any).full_state with a typed intersection ConversationInfo & { full_state?: ConversationInfo } preserves the unwrap behavior without weakening types. Good.

  • getWorkspace() return type (ConversationInfo['workspace'] = unknown) and modelDump() (Record<string, unknown>) are correct tightenings from any. Callers depending on the old any ergonomics will now get compile-time narrowing requirements, which is the intended ratchet effect.

  • Budget tooling is sound. The checker keys sites by module::semantic-path::kind with occurrence dedup, fingerprints the containing type node text, excludes dist/generated/, and enforces add/widen/change/remove failures. The self-test covers the four comparison cases plus budget-document validation. check:public-type-budget builds first so it always scans fresh .d.ts output.

  • Canonical MCP type aliases in clients.ts/index.ts are pure type-level re-exports with no runtime impact.

  • CI/pre-commit integration runs both the self-test and the budget check, matching the documented workflow.

Risk assessment

Low risk. This is a chore/type-safety PR. The only runtime behavioral change (updateStateFromEvent now throws on non-object full-state values instead of silently corrupting the cache) is strictly more defensive and is covered by a regression test. No public API signatures change beyond type tightening, and generated declarations remain governed by the separate OpenAPI drift check.

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

Labels

type: chore Maintenance / chores

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ratchet weak public API types after the Agent Server contract rollout

2 participants