Skip to content

feat(protocol): graduate session instruction entries from experimental - #56688

Draft
kitlangton wants to merge 2 commits into
devfrom
feat/graduate-instruction-entries
Draft

kitlangton wants to merge 2 commits into
devfrom
feat/graduate-instruction-entries

Conversation

@kitlangton

@kitlangton kitlangton commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Why

Session instruction entries were originally added as stable /api/session/:sessionID/context-entry in #34941 (2026-07-02), renamed to /api/session/:sessionID/instructions/entries in #35583 (2026-07-06), and moved under /api/experimental/ in 648d01eec7 (#49067, 2026-09-14) during the V2 HTTP API audit (V2_HTTP_API_AUDIT.md rows 077–079) because there was no first-party caller at the time.

The plugin SDK change in #56550 exposes ctx.session.instructions.entry.{list,put,remove} for keyed, replaceable, durable instructions that announce updates at the next step boundary. GenUI #56548 fixes the immediate extra-step bug with SystemPart and does not use instruction entries; moving GenUI onto keyed entries remains a separate follow-up. Neither change requires these HTTP routes to graduate, so this PR proposes a stable HTTP commitment alongside that plugin surface.

What Changes

Graduate the three session instruction entry endpoints back to /api/session/:sessionID/instructions/entries[/:key] while keeping the /api/experimental/... paths as deprecated aliases sharing the same handlers and middleware:

Method Stable Path Stable Operation ID Deprecated Alias Path Deprecated Operation ID
GET /api/session/:sessionID/instructions/entries session.instructions.entry.list /api/experimental/session/:sessionID/instructions/entries experimental.session.instructions.entry.list (deprecated: true)
PUT /api/session/:sessionID/instructions/entries/:key session.instructions.entry.put /api/experimental/session/:sessionID/instructions/entries/:key experimental.session.instructions.entry.put (deprecated: true)
DELETE /api/session/:sessionID/instructions/entries/:key session.instructions.entry.remove /api/experimental/session/:sessionID/instructions/entries/:key experimental.session.instructions.entry.remove (deprecated: true)
  • Server & OpenAPI (packages/protocol, packages/server, services/www): Both route sets use sessionLocationMiddleware and share the same SessionHandler implementations (listInstructionEntries, putInstructionEntry, removeInstructionEntry). The experimental aliases remain in openapi.json with deprecated: true and descriptions pointing to the stable operations.
  • Generated Clients (packages/protocol/src/client.ts, packages/client): Both session.instructions.entry.* and experimental.session.instructions.entry.* live in SessionGroup and project to the same client path (session.instructions.entry.*). Because @opencode/httpapi-codegen intentionally keeps endpoint filtering policy in the caller rather than applying implicit annotation rules (packages/httpapi-codegen/README.md), the deprecated alias operation IDs are omitted via promiseOmitEndpoints and effectOmitEndpoints so generated Promise and Effect clients expose a single client.session.instructions.entry.{list,put,remove} tree hitting /api/session/:sessionID/instructions/entries[/:key].
  • Audit Checklist (V2_HTTP_API_AUDIT.md): Rows 077–079 now record the Keep disposition on the stable routes alongside the deprecated /api/experimental/... aliases.

Open Question for @thdxr / Dax

  1. Reversing the audit disposition: Does graduating session.instructions.entry.{list,put,remove} back to /api/session/:sessionID/instructions/entries[/:key] look good to you alongside the plugin SDK surface (feat(plugin): expose session instruction entries to plugins #56550) and the planned GenUI migration to keyed entries? GenUI fix(genui): stop GenUI reminder from triggering an extra turn #56548 itself uses SystemPart, not this API.
  2. Deprecated alias retention window: We kept /api/experimental/session/:sessionID/instructions/entries[/:key] as deprecated: true aliases so any existing callers on the experimental URLs don't break immediately. Proposal: keep the aliases for two minor releases (or remove them right away if we don't need a compatibility window for /api/experimental/).

Scope

This PR owns graduating the session instruction entry HTTP routes to /api/session/:sessionID/instructions/entries[/:key], retaining deprecated /api/experimental/... aliases on the server and in OpenAPI, and updating generated clients and tests. Instruction entry key validation hardening is tracked in a separate PR.

Verification

taskpolicy -c utility bun run --cwd packages/protocol check:generated
taskpolicy -c utility bun run --cwd packages/protocol typecheck
taskpolicy -c utility bun run --cwd packages/protocol test
taskpolicy -c utility bun run --cwd packages/client check:generated
taskpolicy -c utility bun run --cwd packages/client typecheck
taskpolicy -c utility bun --cwd packages/client test test/promise.test.ts test/effect.test.ts
taskpolicy -c utility bun run --cwd packages/server typecheck
taskpolicy -c utility bun --cwd packages/server test test/fetch.test.ts
taskpolicy -c utility bun run --cwd packages/sdk typecheck
taskpolicy -c utility bun --cwd packages/sdk test test/contract-identity.test.ts
taskpolicy -c utility bun run --cwd services/www check:generated
  • packages/protocol: OpenAPI generation check, typecheck, and 9/9 tests passed.
  • packages/client: client codegen check, typecheck, and 49/49 Promise + Effect client tests passed against /api/session/:sessionID/instructions/entries[/:key].
  • packages/server: typecheck and 13/13 test/fetch.test.ts tests passed, including sessionLocationMiddleware checks and shared-state roundtrips across /api/session/:sessionID/instructions/entries[/:key] and /api/experimental/session/:sessionID/instructions/entries[/:key].
  • packages/sdk: typecheck and 4/4 test/contract-identity.test.ts tests passed.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant