From 75f046212fc1e12cf0b4b39bd34345fdfefe6ca2 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 14 Sep 2026 13:46:04 -0400 Subject: [PATCH] refactor(protocol): mark transient session controls --- V2_HTTP_API_AUDIT.md | 4 ++-- packages/client/src/effect/api/api.ts | 2 +- packages/client/src/promise/generated/client.ts | 2 +- packages/protocol/openapi.json | 7 +++---- packages/protocol/src/groups/session.ts | 15 +++++++++++---- packages/server/src/handlers/session.ts | 2 +- services/www/openapi.json | 7 +++---- services/www/public/openapi.json | 7 +++---- 8 files changed, 25 insertions(+), 21 deletions(-) diff --git a/V2_HTTP_API_AUDIT.md b/V2_HTTP_API_AUDIT.md index ab0c1e48f35..59bc9b1c2ee 100644 --- a/V2_HTTP_API_AUDIT.md +++ b/V2_HTTP_API_AUDIT.md @@ -166,8 +166,8 @@ Review endpoints in document order. For each endpoint, select one disposition an | [x] 065 | `POST` | `/api/experimental/session/{sessionID}/wait` | `experimental.session.wait` | Experimental-only | Race-free idle barrier retained outside the stable API. | | [x] 066 | `POST` | `/api/session/{sessionID}/generate` | `session.generate` | Keep | Transient generation from session context retained. | | [x] 067 | `POST` | `/api/session/{sessionID}/interrupt` | `session.interrupt` | Change | Renamed `continue` to `resume` across public and internal interruption APIs. | -| [ ] 068 | `PUT` | `/api/session/{sessionID}/environment` | `session.environment` | | | -| [ ] 069 | `POST` | `/api/session/{sessionID}/view` | `session.view` | | | +| [x] 068 | `PUT` | `/api/experimental/session/{sessionID}/environment` | `experimental.session.environment` | Experimental-only | Process-local environment replacement retained outside the stable API. | +| [x] 069 | `POST` | `/api/session/{sessionID}/view` | `session.view` | Change | Idle watermark now uses the standard epoch-millisecond timestamp schema. | ## Group 6: Session history and recovery diff --git a/packages/client/src/effect/api/api.ts b/packages/client/src/effect/api/api.ts index 20bae58f494..5b1b8e4f0ea 100644 --- a/packages/client/src/effect/api/api.ts +++ b/packages/client/src/effect/api/api.ts @@ -1332,7 +1332,7 @@ export type SessionEnvironmentOperation = ( input: SessionEnvironmentInput, ) => Effect.Effect -export type SessionViewInput = { readonly sessionID: Session.ID; readonly idle: number } +export type SessionViewInput = { readonly sessionID: Session.ID; readonly idle: DateTime.Utc } export type SessionViewOutput = void export type SessionViewOperation = (input: SessionViewInput) => Effect.Effect diff --git a/packages/client/src/promise/generated/client.ts b/packages/client/src/promise/generated/client.ts index 21de9edba6e..711c308f4cf 100644 --- a/packages/client/src/promise/generated/client.ts +++ b/packages/client/src/promise/generated/client.ts @@ -979,7 +979,7 @@ export function make(options: ClientOptions) { request( { method: "PUT", - path: `/api/session/${encodeURIComponent(input.sessionID)}/environment`, + path: `/api/experimental/session/${encodeURIComponent(input.sessionID)}/environment`, body: { variables: input["variables"] }, successStatus: 204, declaredStatuses: [400, 401, 404], diff --git a/packages/protocol/openapi.json b/packages/protocol/openapi.json index 366b20392a8..e16e27ec2f3 100644 --- a/packages/protocol/openapi.json +++ b/packages/protocol/openapi.json @@ -4222,10 +4222,10 @@ "summary": "Get session message" } }, - "/api/session/{sessionID}/environment": { + "/api/experimental/session/{sessionID}/environment": { "put": { "tags": ["session"], - "operationId": "session.environment", + "operationId": "experimental.session.environment", "parameters": [ { "name": "sessionID", @@ -4357,8 +4357,7 @@ "type": "object", "properties": { "idle": { - "type": "integer", - "minimum": 0 + "type": "number" } }, "required": ["idle"], diff --git a/packages/protocol/src/groups/session.ts b/packages/protocol/src/groups/session.ts index 79b5e738d01..af7de383a55 100644 --- a/packages/protocol/src/groups/session.ts +++ b/packages/protocol/src/groups/session.ts @@ -5,7 +5,14 @@ import { Session } from "@opencode/schema/session" import { SessionStats } from "@opencode/schema/session-stats" import { InstructionEntry } from "@opencode/schema/instruction-entry" import { Project } from "@opencode/schema/project" -import { AbsolutePath, NonNegativeInt, PositiveInt, RelativePath, statics } from "@opencode/schema/schema" +import { + AbsolutePath, + DateTimeUtcFromMillis, + NonNegativeInt, + PositiveInt, + RelativePath, + statics, +} from "@opencode/schema/schema" import { Event } from "@opencode/schema/event" import { Context, Effect, Encoding, Result, Schema, SchemaGetter, Struct } from "effect" import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi" @@ -764,14 +771,14 @@ export const makeSessionGroup = (sessionLo ), ) .add( - HttpApiEndpoint.put("session.environment", "/api/session/:sessionID/environment", { + HttpApiEndpoint.put("session.environment", "/api/experimental/session/:sessionID/environment", { params: { sessionID: Session.ID }, payload: Schema.Struct({ variables: Schema.Record(Schema.String, Schema.String) }), success: HttpApiSchema.NoContent, error: SessionNotFoundError, }).annotateMerge( OpenApi.annotations({ - identifier: "session.environment", + identifier: "experimental.session.environment", summary: "Set session environment", description: "Replace the process environment used by local shell commands for this session.", }), @@ -780,7 +787,7 @@ export const makeSessionGroup = (sessionLo .add( HttpApiEndpoint.post("session.view", "/api/session/:sessionID/view", { params: { sessionID: Session.ID }, - payload: Schema.Struct({ idle: NonNegativeInt }), + payload: Schema.Struct({ idle: DateTimeUtcFromMillis }), success: HttpApiSchema.NoContent, error: SessionNotFoundError, }).annotateMerge( diff --git a/packages/server/src/handlers/session.ts b/packages/server/src/handlers/session.ts index 4001a75f35b..59b19e0bd5d 100644 --- a/packages/server/src/handlers/session.ts +++ b/packages/server/src/handlers/session.ts @@ -184,7 +184,7 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl "session.view", Effect.fn(function* (ctx) { yield* session - .view({ sessionID: ctx.params.sessionID, idle: ctx.payload.idle }) + .view({ sessionID: ctx.params.sessionID, idle: DateTime.toEpochMillis(ctx.payload.idle) }) .pipe(Effect.catchTag("Session.NotFoundError", missingSession)) return HttpApiSchema.NoContent.make() }), diff --git a/services/www/openapi.json b/services/www/openapi.json index 366b20392a8..e16e27ec2f3 100644 --- a/services/www/openapi.json +++ b/services/www/openapi.json @@ -4222,10 +4222,10 @@ "summary": "Get session message" } }, - "/api/session/{sessionID}/environment": { + "/api/experimental/session/{sessionID}/environment": { "put": { "tags": ["session"], - "operationId": "session.environment", + "operationId": "experimental.session.environment", "parameters": [ { "name": "sessionID", @@ -4357,8 +4357,7 @@ "type": "object", "properties": { "idle": { - "type": "integer", - "minimum": 0 + "type": "number" } }, "required": ["idle"], diff --git a/services/www/public/openapi.json b/services/www/public/openapi.json index 366b20392a8..e16e27ec2f3 100644 --- a/services/www/public/openapi.json +++ b/services/www/public/openapi.json @@ -4222,10 +4222,10 @@ "summary": "Get session message" } }, - "/api/session/{sessionID}/environment": { + "/api/experimental/session/{sessionID}/environment": { "put": { "tags": ["session"], - "operationId": "session.environment", + "operationId": "experimental.session.environment", "parameters": [ { "name": "sessionID", @@ -4357,8 +4357,7 @@ "type": "object", "properties": { "idle": { - "type": "integer", - "minimum": 0 + "type": "number" } }, "required": ["idle"],