@opencode/protocol 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +4 -6
- package/dist/api.js +4 -8
- package/dist/client.d.ts +0 -2
- package/dist/client.js +0 -2
- package/dist/errors.d.ts +20 -0
- package/dist/errors.js +17 -0
- package/dist/groups/agent.d.ts +6 -5
- package/dist/groups/agent.js +2 -2
- package/dist/groups/command.d.ts +3 -3
- package/dist/groups/command.js +1 -1
- package/dist/groups/config.d.ts +5 -13
- package/dist/groups/config.js +11 -18
- package/dist/groups/credential.d.ts +3 -18
- package/dist/groups/credential.js +3 -10
- package/dist/groups/debug.d.ts +0 -8
- package/dist/groups/debug.js +3 -3
- package/dist/groups/event.d.ts +99 -74
- package/dist/groups/event.js +3 -3
- package/dist/groups/form.d.ts +6 -654
- package/dist/groups/form.js +6 -83
- package/dist/groups/fs.d.ts +6 -6
- package/dist/groups/fs.js +3 -3
- package/dist/groups/generate.d.ts +1 -1
- package/dist/groups/generate.js +2 -2
- package/dist/groups/integration.d.ts +27 -27
- package/dist/groups/integration.js +19 -16
- package/dist/groups/location.d.ts +10 -4
- package/dist/groups/location.js +2 -3
- package/dist/groups/mcp.d.ts +11 -13
- package/dist/groups/mcp.js +10 -10
- package/dist/groups/message.d.ts +698 -40
- package/dist/groups/message.js +26 -3
- package/dist/groups/migration.js +1 -1
- package/dist/groups/model.d.ts +12 -9
- package/dist/groups/model.js +2 -2
- package/dist/groups/permission.d.ts +9 -16
- package/dist/groups/permission.js +8 -20
- package/dist/groups/persistent-pty.js +1 -1
- package/dist/groups/plugin.d.ts +7 -12
- package/dist/groups/plugin.js +3 -13
- package/dist/groups/project.d.ts +1 -14
- package/dist/groups/project.js +2 -13
- package/dist/groups/provider.d.ts +8 -7
- package/dist/groups/provider.js +2 -2
- package/dist/groups/pty.d.ts +15 -12
- package/dist/groups/pty.js +8 -8
- package/dist/groups/reference.d.ts +8 -12
- package/dist/groups/reference.js +16 -3
- package/dist/groups/rpc.d.ts +0 -1
- package/dist/groups/rpc.js +1 -1
- package/dist/groups/server.d.ts +9 -1
- package/dist/groups/server.js +11 -5
- package/dist/groups/session.d.ts +1085 -793
- package/dist/groups/session.js +172 -94
- package/dist/groups/shell.d.ts +13 -43
- package/dist/groups/shell.js +6 -24
- package/dist/groups/skill.d.ts +4 -5
- package/dist/groups/skill.js +1 -1
- package/dist/groups/vcs.d.ts +17 -12
- package/dist/groups/vcs.js +6 -6
- package/dist/groups/websearch.d.ts +6 -5
- package/dist/groups/websearch.js +2 -2
- package/dist/groups/worktree.d.ts +17 -23
- package/dist/groups/worktree.js +21 -30
- package/package.json +2 -2
- package/dist/groups/health.d.ts +0 -15
- package/dist/groups/health.js +0 -20
- package/dist/groups/workspace.d.ts +0 -22
- package/dist/groups/workspace.js +0 -27
package/dist/groups/session.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { SessionMessage } from "@opencode/schema/session-message";
|
|
2
|
-
import { SessionTransfer } from "@opencode/schema/session-transfer";
|
|
3
2
|
import { SessionInbox } from "@opencode/schema/session-inbox";
|
|
4
3
|
import { PromptInput } from "@opencode/schema/prompt-input";
|
|
5
4
|
import { Session } from "@opencode/schema/session";
|
|
6
5
|
import { SessionStats } from "@opencode/schema/session-stats";
|
|
7
6
|
import { InstructionEntry } from "@opencode/schema/instruction-entry";
|
|
8
7
|
import { Project } from "@opencode/schema/project";
|
|
9
|
-
import { AbsolutePath, NonNegativeInt, PositiveInt, RelativePath, statics } from "@opencode/schema/schema";
|
|
8
|
+
import { AbsolutePath, DateTimeUtcFromMillis, NonNegativeInt, PositiveInt, RelativePath, statics, } from "@opencode/schema/schema";
|
|
10
9
|
import { Event } from "@opencode/schema/event";
|
|
11
|
-
import { Workspace } from "@opencode/schema/workspace";
|
|
12
10
|
import { Context, Effect, Encoding, Result, Schema, SchemaGetter, Struct } from "effect";
|
|
13
11
|
import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
|
|
14
|
-
import { ConflictError, CommandExecutionError, CommandNotFoundError, InvalidCursorError, InvalidRequestError, MessageNotFoundError, ServiceUnavailableError, SessionBusyError, SessionNotFoundError, SkillNotFoundError, UnknownError, } from "../errors.js";
|
|
12
|
+
import { ConflictError, CommandExecutionError, CommandNotFoundError, FormAlreadySettledError, FormInvalidAnswerError, FormNotFoundError, InvalidCursorError, InvalidRequestError, MessageNotFoundError, ServiceUnavailableError, SessionBusyError, SessionNotFoundError, SkillNotFoundError, UnknownError, } from "../errors.js";
|
|
15
13
|
import { Agent } from "@opencode/schema/agent";
|
|
16
14
|
import { Skill } from "@opencode/schema/skill";
|
|
17
15
|
import { Model } from "@opencode/schema/model";
|
|
@@ -20,6 +18,8 @@ import { Location } from "@opencode/schema/location";
|
|
|
20
18
|
import { SessionEvent } from "@opencode/schema/session-event";
|
|
21
19
|
import { EventLog } from "@opencode/schema/event-log";
|
|
22
20
|
import { FileDiff } from "@opencode/schema/file-diff";
|
|
21
|
+
import { Form } from "@opencode/schema/form";
|
|
22
|
+
import { PublicSessionMessage } from "./message.js";
|
|
23
23
|
const ParentIDFilter = Schema.Union([
|
|
24
24
|
Session.ID,
|
|
25
25
|
Schema.Null.pipe(Schema.encodeTo(Schema.Literal("null"), {
|
|
@@ -30,7 +30,6 @@ const ParentIDFilter = Schema.Union([
|
|
|
30
30
|
description: "Filter by parent session. Use null to return only root sessions.",
|
|
31
31
|
});
|
|
32
32
|
const SessionsQueryFields = {
|
|
33
|
-
workspace: Workspace.ID.pipe(Schema.optional),
|
|
34
33
|
limit: Schema.NumberFromString.pipe(Schema.decodeTo(PositiveInt), Schema.optional).annotate({
|
|
35
34
|
description: "Maximum number of sessions to return. Defaults to the newest 50 sessions.",
|
|
36
35
|
}),
|
|
@@ -78,6 +77,34 @@ export const SessionsCursor = Schema.String.pipe(Schema.brand("SessionsCursor"),
|
|
|
78
77
|
const SessionActive = Schema.Struct({
|
|
79
78
|
type: Schema.Literal("running"),
|
|
80
79
|
}).annotate({ identifier: "SessionActive" });
|
|
80
|
+
const PublicSessionInfo = Schema.Struct({
|
|
81
|
+
...Struct.omit(Session.Info.fields, ["location"]),
|
|
82
|
+
location: Location.PublicRef,
|
|
83
|
+
}).annotate({ identifier: "Session.Info" });
|
|
84
|
+
const PublicSessionTransfer = Schema.Struct({
|
|
85
|
+
info: PublicSessionInfo,
|
|
86
|
+
messages: Schema.Array(PublicSessionMessage),
|
|
87
|
+
}).annotate({ identifier: "SessionTransfer.Data" });
|
|
88
|
+
const PublicMovePayload = Schema.Struct({
|
|
89
|
+
...Struct.omit(SessionInbox.MovePayload.fields, ["location"]),
|
|
90
|
+
location: Location.PublicRef,
|
|
91
|
+
}).annotate({ identifier: "Session.Inbox.MovePayload" });
|
|
92
|
+
const PublicMove = Schema.Struct({
|
|
93
|
+
...Struct.omit(SessionInbox.Move.fields, ["payload"]),
|
|
94
|
+
payload: PublicMovePayload,
|
|
95
|
+
}).annotate({ identifier: "Session.Inbox.Move" });
|
|
96
|
+
const PublicInboxInfo = Schema.Union([
|
|
97
|
+
SessionInbox.User,
|
|
98
|
+
SessionInbox.Synthetic,
|
|
99
|
+
SessionInbox.Compaction,
|
|
100
|
+
PublicMove,
|
|
101
|
+
]).annotate({ identifier: "Session.Inbox.Info" });
|
|
102
|
+
const FormCreatePayload = Schema.Struct({
|
|
103
|
+
id: Form.ID.pipe(Schema.optional),
|
|
104
|
+
title: Form.Info.fields.title,
|
|
105
|
+
metadata: Form.Info.fields.metadata,
|
|
106
|
+
fields: Form.Info.fields.fields,
|
|
107
|
+
}).annotate({ identifier: "Form.CreatePayload" });
|
|
81
108
|
const BooleanFromString = Schema.Literals(["true", "false"]).pipe(Schema.decodeTo(Schema.Boolean, {
|
|
82
109
|
decode: SchemaGetter.transform((value) => value === "true"),
|
|
83
110
|
encode: SchemaGetter.transform((value) => (value ? "true" : "false")),
|
|
@@ -92,11 +119,11 @@ export const SessionsQuery = Schema.Struct({
|
|
|
92
119
|
subpath: RelativePath.pipe(Schema.optional),
|
|
93
120
|
cursor: SessionsQueryCursor.pipe(Schema.optional),
|
|
94
121
|
}).annotate({ identifier: "SessionsQuery" });
|
|
95
|
-
export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make("server.session")
|
|
122
|
+
export const makeSessionGroup = (sessionLocationMiddleware, formLocationMiddleware) => HttpApiGroup.make("server.session")
|
|
96
123
|
.add(HttpApiEndpoint.get("session.list", "/api/session", {
|
|
97
124
|
query: SessionsQuery,
|
|
98
125
|
success: Schema.Struct({
|
|
99
|
-
data: Schema.Array(
|
|
126
|
+
data: Schema.Array(PublicSessionInfo),
|
|
100
127
|
cursor: Schema.Struct({
|
|
101
128
|
previous: SessionsCursor.pipe(Schema.optional),
|
|
102
129
|
next: SessionsCursor.pipe(Schema.optional),
|
|
@@ -104,11 +131,11 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
104
131
|
}).annotate({ identifier: "SessionsResponse" }),
|
|
105
132
|
error: [InvalidCursorError, InvalidRequestError],
|
|
106
133
|
}).annotateMerge(OpenApi.annotations({
|
|
107
|
-
identifier: "
|
|
134
|
+
identifier: "session.list",
|
|
108
135
|
summary: "List sessions",
|
|
109
136
|
description: "Retrieve sessions in the requested order. Items keep that order across pages; use cursor.next or cursor.previous to move through the ordered list.",
|
|
110
137
|
})))
|
|
111
|
-
.add(HttpApiEndpoint.get("session.stats", "/api/session/stats", {
|
|
138
|
+
.add(HttpApiEndpoint.get("session.stats", "/api/experimental/session/stats", {
|
|
112
139
|
query: Schema.Struct({
|
|
113
140
|
from: Schema.NumberFromString.pipe(Schema.optional),
|
|
114
141
|
to: Schema.NumberFromString.pipe(Schema.optional),
|
|
@@ -119,7 +146,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
119
146
|
success: Schema.Struct({ data: SessionStats.Info }),
|
|
120
147
|
error: InvalidRequestError,
|
|
121
148
|
}).annotateMerge(OpenApi.annotations({
|
|
122
|
-
identifier: "
|
|
149
|
+
identifier: "experimental.session.stats",
|
|
123
150
|
summary: "Get session statistics",
|
|
124
151
|
description: "Aggregate local session activity, usage, and tool reliability for a time range.",
|
|
125
152
|
})))
|
|
@@ -129,51 +156,51 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
129
156
|
title: Schema.String.pipe(Schema.optional),
|
|
130
157
|
agent: Agent.ID.pipe(Schema.optional),
|
|
131
158
|
model: Model.Ref.pipe(Schema.optional),
|
|
132
|
-
location: Location.
|
|
159
|
+
location: Location.PublicRef.pipe(Schema.optional),
|
|
133
160
|
metadata: Session.Metadata.pipe(Schema.optional),
|
|
134
161
|
permissions: Permission.Ruleset.pipe(Schema.optional),
|
|
135
162
|
}),
|
|
136
|
-
success: Schema.Struct({ data:
|
|
163
|
+
success: Schema.Struct({ data: PublicSessionInfo }),
|
|
137
164
|
}).annotateMerge(OpenApi.annotations({
|
|
138
|
-
identifier: "
|
|
165
|
+
identifier: "session.create",
|
|
139
166
|
summary: "Create session",
|
|
140
167
|
description: "Create a session at the requested location.",
|
|
141
168
|
})))
|
|
142
|
-
.add(HttpApiEndpoint.post("session.import", "/api/session/import", {
|
|
169
|
+
.add(HttpApiEndpoint.post("session.import", "/api/experimental/session/import", {
|
|
143
170
|
payload: Schema.Struct({
|
|
144
|
-
...
|
|
145
|
-
location: Location.
|
|
171
|
+
...PublicSessionTransfer.fields,
|
|
172
|
+
location: Location.PublicRef.pipe(Schema.optional),
|
|
146
173
|
}),
|
|
147
|
-
success: Schema.Struct({ data:
|
|
174
|
+
success: Schema.Struct({ data: PublicSessionInfo }),
|
|
148
175
|
error: [ConflictError, SessionNotFoundError],
|
|
149
176
|
}).annotateMerge(OpenApi.annotations({
|
|
150
|
-
identifier: "
|
|
177
|
+
identifier: "experimental.session.import",
|
|
151
178
|
summary: "Import session",
|
|
152
179
|
description: "Import a projected session transcript at the requested location. If parentID is supplied, the parent session must already exist; import parents before children.",
|
|
153
180
|
})))
|
|
154
|
-
.add(HttpApiEndpoint.get("session.export", "/api/session/:sessionID/export", {
|
|
181
|
+
.add(HttpApiEndpoint.get("session.export", "/api/experimental/session/:sessionID/export", {
|
|
155
182
|
params: { sessionID: Session.ID },
|
|
156
183
|
query: Schema.Struct({ sanitize: BooleanFromString.pipe(Schema.optional) }),
|
|
157
|
-
success: Schema.Struct({ data:
|
|
184
|
+
success: Schema.Struct({ data: PublicSessionTransfer }),
|
|
158
185
|
error: [SessionNotFoundError, UnknownError],
|
|
159
186
|
}).annotateMerge(OpenApi.annotations({
|
|
160
|
-
identifier: "
|
|
187
|
+
identifier: "experimental.session.export",
|
|
161
188
|
summary: "Export session",
|
|
162
189
|
description: "Export a complete projected session transcript.",
|
|
163
190
|
})))
|
|
164
191
|
.add(HttpApiEndpoint.get("session.active", "/api/session/active", {
|
|
165
192
|
success: Schema.Struct({ data: Schema.Record(Session.ID, SessionActive) }),
|
|
166
193
|
}).annotateMerge(OpenApi.annotations({
|
|
167
|
-
identifier: "
|
|
194
|
+
identifier: "session.active",
|
|
168
195
|
summary: "List active sessions",
|
|
169
196
|
description: "Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive.",
|
|
170
197
|
})))
|
|
171
198
|
.add(HttpApiEndpoint.get("session.get", "/api/session/:sessionID", {
|
|
172
199
|
params: { sessionID: Session.ID },
|
|
173
|
-
success: Schema.Struct({ data:
|
|
200
|
+
success: Schema.Struct({ data: PublicSessionInfo }),
|
|
174
201
|
error: SessionNotFoundError,
|
|
175
202
|
}).annotateMerge(OpenApi.annotations({
|
|
176
|
-
identifier: "
|
|
203
|
+
identifier: "session.get",
|
|
177
204
|
summary: "Get session",
|
|
178
205
|
description: "Retrieve a session by ID.",
|
|
179
206
|
})))
|
|
@@ -182,21 +209,21 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
182
209
|
success: HttpApiSchema.NoContent,
|
|
183
210
|
error: SessionNotFoundError,
|
|
184
211
|
}).annotateMerge(OpenApi.annotations({
|
|
185
|
-
identifier: "
|
|
212
|
+
identifier: "session.remove",
|
|
186
213
|
summary: "Delete session",
|
|
187
214
|
description: "Delete a session and its child sessions.",
|
|
188
215
|
})))
|
|
189
216
|
.add(HttpApiEndpoint.post("session.fork", "/api/session/:sessionID/fork", {
|
|
190
217
|
params: { sessionID: Session.ID },
|
|
191
|
-
payload: Schema.Struct({
|
|
192
|
-
success: Schema.Struct({ data:
|
|
218
|
+
payload: Schema.Struct({ before: SessionMessage.ID.pipe(Schema.optional) }),
|
|
219
|
+
success: Schema.Struct({ data: PublicSessionInfo }),
|
|
193
220
|
error: [SessionNotFoundError, MessageNotFoundError, InvalidRequestError],
|
|
194
221
|
})
|
|
195
222
|
.middleware(sessionLocationMiddleware)
|
|
196
223
|
.annotateMerge(OpenApi.annotations({
|
|
197
|
-
identifier: "
|
|
224
|
+
identifier: "session.fork",
|
|
198
225
|
summary: "Fork session",
|
|
199
|
-
description: "Create a child session by copying projected history
|
|
226
|
+
description: "Create a child session by copying projected history before a message. Omit before to copy the full history.",
|
|
200
227
|
})))
|
|
201
228
|
.add(HttpApiEndpoint.post("session.switchAgent", "/api/session/:sessionID/agent", {
|
|
202
229
|
params: { sessionID: Session.ID },
|
|
@@ -206,7 +233,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
206
233
|
})
|
|
207
234
|
.middleware(sessionLocationMiddleware)
|
|
208
235
|
.annotateMerge(OpenApi.annotations({
|
|
209
|
-
identifier: "
|
|
236
|
+
identifier: "session.switchAgent",
|
|
210
237
|
summary: "Switch session agent",
|
|
211
238
|
description: "Switch the agent used by subsequent provider turns.",
|
|
212
239
|
})))
|
|
@@ -218,31 +245,34 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
218
245
|
})
|
|
219
246
|
.middleware(sessionLocationMiddleware)
|
|
220
247
|
.annotateMerge(OpenApi.annotations({
|
|
221
|
-
identifier: "
|
|
248
|
+
identifier: "session.switchModel",
|
|
222
249
|
summary: "Switch session model",
|
|
223
250
|
description: "Switch the model used by subsequent provider turns.",
|
|
224
251
|
})))
|
|
225
|
-
.add(HttpApiEndpoint.
|
|
252
|
+
.add(HttpApiEndpoint.patch("session.update", "/api/session/:sessionID", {
|
|
226
253
|
params: { sessionID: Session.ID },
|
|
227
|
-
payload: Schema.Struct({
|
|
254
|
+
payload: Schema.Struct({
|
|
255
|
+
title: Schema.String.pipe(Schema.optional),
|
|
256
|
+
permissions: Permission.Ruleset.pipe(Schema.optional),
|
|
257
|
+
}),
|
|
228
258
|
success: HttpApiSchema.NoContent,
|
|
229
259
|
error: SessionNotFoundError,
|
|
230
260
|
})
|
|
231
261
|
.middleware(sessionLocationMiddleware)
|
|
232
262
|
.annotateMerge(OpenApi.annotations({
|
|
233
|
-
identifier: "
|
|
234
|
-
summary: "
|
|
235
|
-
description: "Update
|
|
263
|
+
identifier: "session.update",
|
|
264
|
+
summary: "Update session",
|
|
265
|
+
description: "Update mutable session properties.",
|
|
236
266
|
})))
|
|
237
267
|
.add(HttpApiEndpoint.post("session.move", "/api/session/:sessionID/move", {
|
|
238
268
|
params: { sessionID: Session.ID },
|
|
239
|
-
payload: Schema.Struct({ ...Location.
|
|
269
|
+
payload: Schema.Struct({ ...Location.PublicRef.fields, delivery: SessionInbox.Delivery.pipe(Schema.optional) }),
|
|
240
270
|
success: HttpApiSchema.NoContent,
|
|
241
271
|
error: [SessionNotFoundError, InvalidRequestError],
|
|
242
272
|
}).annotateMerge(OpenApi.annotations({
|
|
243
|
-
identifier: "
|
|
273
|
+
identifier: "session.move",
|
|
244
274
|
summary: "Move session",
|
|
245
|
-
description: "Move a session to another project directory
|
|
275
|
+
description: "Move a session to another project directory at the requested delivery boundary.",
|
|
246
276
|
})))
|
|
247
277
|
.add(HttpApiEndpoint.post("session.prompt", "/api/session/:sessionID/prompt", {
|
|
248
278
|
params: { sessionID: Session.ID },
|
|
@@ -258,14 +288,14 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
258
288
|
})
|
|
259
289
|
.middleware(sessionLocationMiddleware)
|
|
260
290
|
.annotateMerge(OpenApi.annotations({
|
|
261
|
-
identifier: "
|
|
291
|
+
identifier: "session.prompt",
|
|
262
292
|
summary: "Send message",
|
|
263
293
|
description: "Durably admit one session input and schedule agent-loop execution unless resume is false.",
|
|
264
294
|
})))
|
|
265
295
|
.add(HttpApiEndpoint.post("session.command", "/api/session/:sessionID/command", {
|
|
266
296
|
params: { sessionID: Session.ID },
|
|
267
297
|
payload: Schema.Struct({
|
|
268
|
-
|
|
298
|
+
name: Schema.String,
|
|
269
299
|
...PromptInput.Prompt.fields,
|
|
270
300
|
delivery: SessionInbox.Delivery.pipe(Schema.optional),
|
|
271
301
|
}),
|
|
@@ -274,15 +304,14 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
274
304
|
})
|
|
275
305
|
.middleware(sessionLocationMiddleware)
|
|
276
306
|
.annotateMerge(OpenApi.annotations({
|
|
277
|
-
identifier: "
|
|
307
|
+
identifier: "session.command",
|
|
278
308
|
summary: "Run command",
|
|
279
309
|
description: "Execute a slash command callback immediately.",
|
|
280
310
|
})))
|
|
281
|
-
.add(HttpApiEndpoint.post("session.skill", "/api/session/:sessionID/skill", {
|
|
311
|
+
.add(HttpApiEndpoint.post("session.skill", "/api/experimental/session/:sessionID/skill", {
|
|
282
312
|
params: { sessionID: Session.ID },
|
|
283
313
|
payload: Schema.Struct({
|
|
284
|
-
id:
|
|
285
|
-
skill: Skill.ID,
|
|
314
|
+
id: Skill.ID,
|
|
286
315
|
resume: Schema.Boolean.pipe(Schema.optional),
|
|
287
316
|
}),
|
|
288
317
|
success: HttpApiSchema.NoContent,
|
|
@@ -290,7 +319,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
290
319
|
})
|
|
291
320
|
.middleware(sessionLocationMiddleware)
|
|
292
321
|
.annotateMerge(OpenApi.annotations({
|
|
293
|
-
identifier: "
|
|
322
|
+
identifier: "experimental.session.skill",
|
|
294
323
|
summary: "Activate skill",
|
|
295
324
|
description: "Activate a skill for a session by appending a skill message and resuming execution.",
|
|
296
325
|
})))
|
|
@@ -309,14 +338,14 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
309
338
|
})
|
|
310
339
|
.middleware(sessionLocationMiddleware)
|
|
311
340
|
.annotateMerge(OpenApi.annotations({
|
|
312
|
-
identifier: "
|
|
341
|
+
identifier: "session.synthetic",
|
|
313
342
|
summary: "Add synthetic message",
|
|
314
343
|
description: "Durably admit synthetic session input and schedule execution unless resume is false.",
|
|
315
344
|
})))
|
|
316
345
|
.add(HttpApiEndpoint.post("session.shell", "/api/session/:sessionID/shell", {
|
|
317
346
|
params: { sessionID: Session.ID },
|
|
318
347
|
payload: Schema.Struct({
|
|
319
|
-
id:
|
|
348
|
+
id: SessionMessage.ID.pipe(Schema.optional),
|
|
320
349
|
command: Schema.String,
|
|
321
350
|
}),
|
|
322
351
|
success: HttpApiSchema.NoContent,
|
|
@@ -324,7 +353,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
324
353
|
})
|
|
325
354
|
.middleware(sessionLocationMiddleware)
|
|
326
355
|
.annotateMerge(OpenApi.annotations({
|
|
327
|
-
identifier: "
|
|
356
|
+
identifier: "session.shell",
|
|
328
357
|
summary: "Run shell command",
|
|
329
358
|
description: "Execute one shell command in the session's working directory. Emits a shell.started event before execution and a shell.ended event with the merged output after.",
|
|
330
359
|
})))
|
|
@@ -339,18 +368,18 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
339
368
|
})
|
|
340
369
|
.middleware(sessionLocationMiddleware)
|
|
341
370
|
.annotateMerge(OpenApi.annotations({
|
|
342
|
-
identifier: "
|
|
371
|
+
identifier: "session.compact",
|
|
343
372
|
summary: "Compact session",
|
|
344
373
|
description: "Durably admit a session compaction request. Steers by default: it runs at the next step boundary instead of waiting behind queued prompts.",
|
|
345
374
|
})))
|
|
346
|
-
.add(HttpApiEndpoint.post("session.wait", "/api/session/:sessionID/wait", {
|
|
375
|
+
.add(HttpApiEndpoint.post("session.wait", "/api/experimental/session/:sessionID/wait", {
|
|
347
376
|
params: { sessionID: Session.ID },
|
|
348
377
|
success: HttpApiSchema.NoContent,
|
|
349
378
|
error: [SessionNotFoundError, ServiceUnavailableError],
|
|
350
379
|
})
|
|
351
380
|
.middleware(sessionLocationMiddleware)
|
|
352
381
|
.annotateMerge(OpenApi.annotations({
|
|
353
|
-
identifier: "
|
|
382
|
+
identifier: "experimental.session.wait",
|
|
354
383
|
summary: "Wait for session",
|
|
355
384
|
description: "Wait for a session agent loop to become idle.",
|
|
356
385
|
})))
|
|
@@ -362,30 +391,30 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
362
391
|
})
|
|
363
392
|
.middleware(sessionLocationMiddleware)
|
|
364
393
|
.annotateMerge(OpenApi.annotations({
|
|
365
|
-
identifier: "
|
|
394
|
+
identifier: "session.revert.stage",
|
|
366
395
|
summary: "Stage session revert",
|
|
367
396
|
description: "Stage or move a reversible session boundary and optionally apply its file changes.",
|
|
368
397
|
})))
|
|
369
|
-
.add(HttpApiEndpoint.
|
|
398
|
+
.add(HttpApiEndpoint.delete("session.revert.clear", "/api/session/:sessionID/revert", {
|
|
370
399
|
params: { sessionID: Session.ID },
|
|
371
400
|
success: HttpApiSchema.NoContent,
|
|
372
401
|
error: [SessionNotFoundError, SessionBusyError, UnknownError],
|
|
373
402
|
})
|
|
374
403
|
.middleware(sessionLocationMiddleware)
|
|
375
|
-
.annotateMerge(OpenApi.annotations({ identifier: "
|
|
404
|
+
.annotateMerge(OpenApi.annotations({ identifier: "session.revert.clear", summary: "Clear staged revert" })))
|
|
376
405
|
.add(HttpApiEndpoint.post("session.revert.commit", "/api/session/:sessionID/revert/commit", {
|
|
377
406
|
params: { sessionID: Session.ID },
|
|
378
407
|
success: HttpApiSchema.NoContent,
|
|
379
408
|
error: [SessionNotFoundError, SessionBusyError],
|
|
380
409
|
})
|
|
381
410
|
.middleware(sessionLocationMiddleware)
|
|
382
|
-
.annotateMerge(OpenApi.annotations({ identifier: "
|
|
411
|
+
.annotateMerge(OpenApi.annotations({ identifier: "session.revert.commit", summary: "Commit staged revert" })))
|
|
383
412
|
.add(HttpApiEndpoint.get("session.context", "/api/session/:sessionID/context", {
|
|
384
413
|
params: { sessionID: Session.ID },
|
|
385
|
-
success: Schema.Struct({ data: Schema.Array(
|
|
414
|
+
success: Schema.Struct({ data: Schema.Array(PublicSessionMessage) }),
|
|
386
415
|
error: [SessionNotFoundError, UnknownError],
|
|
387
416
|
}).annotateMerge(OpenApi.annotations({
|
|
388
|
-
identifier: "
|
|
417
|
+
identifier: "session.context",
|
|
389
418
|
summary: "Get session context",
|
|
390
419
|
description: "Retrieve the active context messages for a session (all messages after the last compaction).",
|
|
391
420
|
})))
|
|
@@ -405,58 +434,50 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
405
434
|
success: Schema.Struct({ data: Schema.Array(FileDiff.Info) }),
|
|
406
435
|
error: [InvalidRequestError, MessageNotFoundError, SessionNotFoundError, UnknownError],
|
|
407
436
|
}).annotateMerge(OpenApi.annotations({
|
|
408
|
-
identifier: "
|
|
437
|
+
identifier: "session.diff",
|
|
409
438
|
summary: "Diff session turns",
|
|
410
439
|
description: "Structured per-file diffs of the files a turn changed. A turn runs from the first prompt after the session was last idle until its next idle marker, so prompts steered in while it was busy belong to the same turn; `to` extends the range through a later turn. Compares the range's first recorded snapshot with its last; a step still running in the active session compares against the working copy. Ranges that span a location change are rejected. In sessions without any idle marker, a prompt's turn spans until the next user message.",
|
|
411
440
|
})))
|
|
412
441
|
.add(HttpApiEndpoint.get("session.inbox.list", "/api/session/:sessionID/inbox", {
|
|
413
442
|
params: { sessionID: Session.ID },
|
|
414
|
-
success: Schema.Struct({ data: Schema.Array(
|
|
443
|
+
success: Schema.Struct({ data: Schema.Array(PublicInboxInfo) }),
|
|
415
444
|
error: SessionNotFoundError,
|
|
416
445
|
}).annotateMerge(OpenApi.annotations({
|
|
417
|
-
identifier: "
|
|
446
|
+
identifier: "session.inbox.list",
|
|
418
447
|
summary: "List session inbox",
|
|
419
448
|
description: "List durable enqueued session work not yet delivered, ordered by enqueue sequence. Includes user, synthetic, compaction, and move items.",
|
|
420
449
|
})))
|
|
421
450
|
.add(HttpApiEndpoint.delete("session.inbox.cancel", "/api/session/:sessionID/inbox/:inboxID", {
|
|
422
451
|
params: { sessionID: Session.ID, inboxID: SessionMessage.ID },
|
|
423
452
|
success: HttpApiSchema.NoContent,
|
|
424
|
-
error:
|
|
453
|
+
error: SessionNotFoundError,
|
|
425
454
|
}).annotateMerge(OpenApi.annotations({
|
|
426
|
-
identifier: "
|
|
455
|
+
identifier: "session.inbox.cancel",
|
|
427
456
|
summary: "Cancel inbox input",
|
|
428
|
-
description: "Cancel an inbox item that has not yet been delivered.",
|
|
457
|
+
description: "Cancel an inbox item that has not yet been delivered. Unavailable items are a no-op.",
|
|
429
458
|
})))
|
|
430
|
-
.add(HttpApiEndpoint.
|
|
459
|
+
.add(HttpApiEndpoint.patch("session.inbox.update", "/api/session/:sessionID/inbox/:inboxID", {
|
|
431
460
|
params: { sessionID: Session.ID, inboxID: SessionMessage.ID },
|
|
461
|
+
payload: Schema.Struct({ delivery: SessionInbox.Delivery }),
|
|
432
462
|
success: HttpApiSchema.NoContent,
|
|
433
463
|
error: [ConflictError, SessionNotFoundError],
|
|
434
464
|
}).annotateMerge(OpenApi.annotations({
|
|
435
|
-
identifier: "
|
|
436
|
-
summary: "
|
|
437
|
-
description: "Change a
|
|
465
|
+
identifier: "session.inbox.update",
|
|
466
|
+
summary: "Update inbox item",
|
|
467
|
+
description: "Change a pending inbox item's delivery mode. Steering wakes session execution.",
|
|
438
468
|
})))
|
|
439
|
-
.add(HttpApiEndpoint.
|
|
440
|
-
params: { sessionID: Session.ID, inboxID: SessionMessage.ID },
|
|
441
|
-
success: HttpApiSchema.NoContent,
|
|
442
|
-
error: [ConflictError, SessionNotFoundError],
|
|
443
|
-
}).annotateMerge(OpenApi.annotations({
|
|
444
|
-
identifier: "v2.session.inbox.queue",
|
|
445
|
-
summary: "Queue steered item",
|
|
446
|
-
description: "Change a steered inbox item to queued delivery.",
|
|
447
|
-
})))
|
|
448
|
-
.add(HttpApiEndpoint.get("session.instructions.entry.list", "/api/session/:sessionID/instructions/entries", {
|
|
469
|
+
.add(HttpApiEndpoint.get("session.instructions.entry.list", "/api/experimental/session/:sessionID/instructions/entries", {
|
|
449
470
|
params: { sessionID: Session.ID },
|
|
450
471
|
success: Schema.Struct({ data: Schema.Array(InstructionEntry.Info) }),
|
|
451
472
|
error: SessionNotFoundError,
|
|
452
473
|
})
|
|
453
474
|
.middleware(sessionLocationMiddleware)
|
|
454
475
|
.annotateMerge(OpenApi.annotations({
|
|
455
|
-
identifier: "
|
|
476
|
+
identifier: "experimental.session.instructions.entry.list",
|
|
456
477
|
summary: "List instruction entries",
|
|
457
478
|
description: "List API-managed instruction entries attached to the session.",
|
|
458
479
|
})))
|
|
459
|
-
.add(HttpApiEndpoint.put("session.instructions.entry.put", "/api/session/:sessionID/instructions/entries/:key", {
|
|
480
|
+
.add(HttpApiEndpoint.put("session.instructions.entry.put", "/api/experimental/session/:sessionID/instructions/entries/:key", {
|
|
460
481
|
params: { sessionID: Session.ID, key: InstructionEntry.Key },
|
|
461
482
|
payload: Schema.Struct({ value: Schema.Json }),
|
|
462
483
|
success: HttpApiSchema.NoContent,
|
|
@@ -464,18 +485,18 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
464
485
|
})
|
|
465
486
|
.middleware(sessionLocationMiddleware)
|
|
466
487
|
.annotateMerge(OpenApi.annotations({
|
|
467
|
-
identifier: "
|
|
488
|
+
identifier: "experimental.session.instructions.entry.put",
|
|
468
489
|
summary: "Put instruction entry",
|
|
469
490
|
description: "Attach or replace one durable instruction entry. Changes announce as updates at the next step boundary.",
|
|
470
491
|
})))
|
|
471
|
-
.add(HttpApiEndpoint.delete("session.instructions.entry.remove", "/api/session/:sessionID/instructions/entries/:key", {
|
|
492
|
+
.add(HttpApiEndpoint.delete("session.instructions.entry.remove", "/api/experimental/session/:sessionID/instructions/entries/:key", {
|
|
472
493
|
params: { sessionID: Session.ID, key: InstructionEntry.Key },
|
|
473
494
|
success: HttpApiSchema.NoContent,
|
|
474
495
|
error: SessionNotFoundError,
|
|
475
496
|
})
|
|
476
497
|
.middleware(sessionLocationMiddleware)
|
|
477
498
|
.annotateMerge(OpenApi.annotations({
|
|
478
|
-
identifier: "
|
|
499
|
+
identifier: "experimental.session.instructions.entry.remove",
|
|
479
500
|
summary: "Remove instruction entry",
|
|
480
501
|
description: "Remove one instruction entry; the removal is announced to the model at the next step boundary.",
|
|
481
502
|
})))
|
|
@@ -489,7 +510,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
489
510
|
})
|
|
490
511
|
.middleware(sessionLocationMiddleware)
|
|
491
512
|
.annotateMerge(OpenApi.annotations({
|
|
492
|
-
identifier: "
|
|
513
|
+
identifier: "session.generate",
|
|
493
514
|
summary: "Generate text from session context",
|
|
494
515
|
description: "Generate transient text from the current session context without mutating session history.",
|
|
495
516
|
})))
|
|
@@ -504,13 +525,13 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
504
525
|
}),
|
|
505
526
|
error: SessionNotFoundError,
|
|
506
527
|
}).annotateMerge(OpenApi.annotations({
|
|
507
|
-
identifier: "
|
|
528
|
+
identifier: "session.log",
|
|
508
529
|
summary: "Read the session log",
|
|
509
530
|
description: "Experimental durable session event log. Reads events after an exclusive aggregate sequence and continues with live events when follow=true.",
|
|
510
531
|
})))
|
|
511
532
|
.add(HttpApiEndpoint.post("session.interrupt", "/api/session/:sessionID/interrupt", {
|
|
512
533
|
params: { sessionID: Session.ID },
|
|
513
|
-
query: {
|
|
534
|
+
query: { resume: BooleanFromString.pipe(Schema.optional) },
|
|
514
535
|
success: Schema.Struct({
|
|
515
536
|
interrupted: Schema.Boolean.annotate({
|
|
516
537
|
description: "Whether an active execution owned by this OpenCode process was interrupted.",
|
|
@@ -520,9 +541,9 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
520
541
|
})
|
|
521
542
|
.middleware(sessionLocationMiddleware)
|
|
522
543
|
.annotateMerge(OpenApi.annotations({
|
|
523
|
-
identifier: "
|
|
544
|
+
identifier: "session.interrupt",
|
|
524
545
|
summary: "Interrupt session execution",
|
|
525
|
-
description: "Interrupt active execution owned by this OpenCode process. Returns interrupted=true when an active execution was interrupted and false for the idle no-op. When
|
|
546
|
+
description: "Interrupt active execution owned by this OpenCode process. Returns interrupted=true when an active execution was interrupted and false for the idle no-op. When resume=true, execution resumes pending steering input and next-in-line control items (manual compaction, moves) while queued prompts remain parked.",
|
|
526
547
|
})))
|
|
527
548
|
.add(HttpApiEndpoint.post("session.background", "/api/session/:sessionID/background", {
|
|
528
549
|
params: { sessionID: Session.ID },
|
|
@@ -531,18 +552,75 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
531
552
|
})
|
|
532
553
|
.middleware(sessionLocationMiddleware)
|
|
533
554
|
.annotateMerge(OpenApi.annotations({
|
|
534
|
-
identifier: "
|
|
555
|
+
identifier: "session.background",
|
|
535
556
|
summary: "Background blocking session tools",
|
|
536
557
|
description: "Move active foreground backgroundable tools for this session into background observation. Idle requests are a no-op.",
|
|
537
558
|
})))
|
|
538
559
|
.add(HttpApiEndpoint.get("session.message", "/api/session/:sessionID/message/:messageID", {
|
|
539
560
|
params: { sessionID: Session.ID, messageID: SessionMessage.ID },
|
|
540
|
-
success: Schema.Struct({ data:
|
|
561
|
+
success: Schema.Struct({ data: PublicSessionMessage }),
|
|
541
562
|
error: [SessionNotFoundError, MessageNotFoundError],
|
|
542
563
|
}).annotateMerge(OpenApi.annotations({
|
|
543
|
-
identifier: "
|
|
564
|
+
identifier: "session.message.get",
|
|
544
565
|
summary: "Get session message",
|
|
545
566
|
description: "Retrieve one projected message owned by the Session.",
|
|
567
|
+
})))
|
|
568
|
+
.add(HttpApiEndpoint.get("session.form.list", "/api/session/:sessionID/form", {
|
|
569
|
+
params: { sessionID: Schema.String },
|
|
570
|
+
success: Schema.Struct({ data: Schema.Array(Form.Info) }),
|
|
571
|
+
error: SessionNotFoundError,
|
|
572
|
+
})
|
|
573
|
+
.middleware(formLocationMiddleware)
|
|
574
|
+
.annotateMerge(OpenApi.annotations({
|
|
575
|
+
identifier: "session.form.list",
|
|
576
|
+
summary: "List session forms",
|
|
577
|
+
description: "Retrieve pending forms for a session.",
|
|
578
|
+
})))
|
|
579
|
+
.add(HttpApiEndpoint.post("session.form.create", "/api/session/:sessionID/form", {
|
|
580
|
+
params: { sessionID: Schema.String },
|
|
581
|
+
payload: FormCreatePayload,
|
|
582
|
+
success: Schema.Struct({ data: Form.Info }),
|
|
583
|
+
error: [SessionNotFoundError, ConflictError, InvalidRequestError],
|
|
584
|
+
})
|
|
585
|
+
.middleware(formLocationMiddleware)
|
|
586
|
+
.annotateMerge(OpenApi.annotations({
|
|
587
|
+
identifier: "session.form.create",
|
|
588
|
+
summary: "Create session form",
|
|
589
|
+
description: "Create a form for a session.",
|
|
590
|
+
})))
|
|
591
|
+
.add(HttpApiEndpoint.get("session.form.get", "/api/session/:sessionID/form/:formID", {
|
|
592
|
+
params: { sessionID: Schema.String, formID: Form.ID },
|
|
593
|
+
success: Schema.Struct({ data: Form.Detail }),
|
|
594
|
+
error: [SessionNotFoundError, FormNotFoundError],
|
|
595
|
+
})
|
|
596
|
+
.middleware(formLocationMiddleware)
|
|
597
|
+
.annotateMerge(OpenApi.annotations({
|
|
598
|
+
identifier: "session.form.get",
|
|
599
|
+
summary: "Get session form",
|
|
600
|
+
description: "Retrieve a form and its current state for a session.",
|
|
601
|
+
})))
|
|
602
|
+
.add(HttpApiEndpoint.post("session.form.reply", "/api/session/:sessionID/form/:formID/reply", {
|
|
603
|
+
params: { sessionID: Schema.String, formID: Form.ID },
|
|
604
|
+
payload: Form.Reply,
|
|
605
|
+
success: HttpApiSchema.NoContent,
|
|
606
|
+
error: [SessionNotFoundError, FormAlreadySettledError, FormInvalidAnswerError, FormNotFoundError],
|
|
607
|
+
})
|
|
608
|
+
.middleware(formLocationMiddleware)
|
|
609
|
+
.annotateMerge(OpenApi.annotations({
|
|
610
|
+
identifier: "session.form.reply",
|
|
611
|
+
summary: "Reply to form",
|
|
612
|
+
description: "Submit an answer to a pending form.",
|
|
613
|
+
})))
|
|
614
|
+
.add(HttpApiEndpoint.delete("session.form.cancel", "/api/session/:sessionID/form/:formID", {
|
|
615
|
+
params: { sessionID: Schema.String, formID: Form.ID },
|
|
616
|
+
success: HttpApiSchema.NoContent,
|
|
617
|
+
error: [SessionNotFoundError, FormAlreadySettledError, FormNotFoundError],
|
|
618
|
+
})
|
|
619
|
+
.middleware(formLocationMiddleware)
|
|
620
|
+
.annotateMerge(OpenApi.annotations({
|
|
621
|
+
identifier: "session.form.cancel",
|
|
622
|
+
summary: "Cancel form",
|
|
623
|
+
description: "Cancel a pending form.",
|
|
546
624
|
})))
|
|
547
625
|
.add(HttpApiEndpoint.put("session.environment", "/api/session/:sessionID/environment", {
|
|
548
626
|
params: { sessionID: Session.ID },
|
|
@@ -550,17 +628,17 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
550
628
|
success: HttpApiSchema.NoContent,
|
|
551
629
|
error: SessionNotFoundError,
|
|
552
630
|
}).annotateMerge(OpenApi.annotations({
|
|
553
|
-
identifier: "
|
|
631
|
+
identifier: "session.environment",
|
|
554
632
|
summary: "Set session environment",
|
|
555
633
|
description: "Replace the process environment used by local shell commands for this session.",
|
|
556
634
|
})))
|
|
557
635
|
.add(HttpApiEndpoint.post("session.view", "/api/session/:sessionID/view", {
|
|
558
636
|
params: { sessionID: Session.ID },
|
|
559
|
-
payload: Schema.Struct({ idle:
|
|
637
|
+
payload: Schema.Struct({ idle: DateTimeUtcFromMillis }),
|
|
560
638
|
success: HttpApiSchema.NoContent,
|
|
561
639
|
error: SessionNotFoundError,
|
|
562
640
|
}).annotateMerge(OpenApi.annotations({
|
|
563
|
-
identifier: "
|
|
641
|
+
identifier: "session.view",
|
|
564
642
|
summary: "View session",
|
|
565
643
|
description: "Mark the idle transition observed by the viewer as viewed.",
|
|
566
644
|
})))
|