@opencode-ai/protocol 0.0.0-next-14722 → 0.0.0-next-14730
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 +11 -8
- package/dist/api.js +5 -5
- package/dist/client.d.ts +3 -3
- package/dist/client.js +5 -2
- package/dist/errors.d.ts +15 -3
- package/dist/errors.js +12 -2
- package/dist/groups/event.d.ts +1711 -1227
- package/dist/groups/event.js +11 -3
- package/dist/groups/form.d.ts +823 -0
- package/dist/groups/form.js +110 -0
- package/dist/groups/message.d.ts +1 -0
- package/dist/groups/message.js +5 -0
- package/dist/groups/session.d.ts +322 -2990
- package/dist/groups/session.js +23 -29
- package/package.json +2 -2
- package/dist/groups/question.d.ts +0 -92
- package/dist/groups/question.js +0 -56
package/dist/groups/session.js
CHANGED
|
@@ -4,9 +4,10 @@ import { PromptInput } from "@opencode-ai/schema/prompt-input";
|
|
|
4
4
|
import { Session } from "@opencode-ai/schema/session";
|
|
5
5
|
import { SessionContextEntry } from "@opencode-ai/schema/session-context-entry";
|
|
6
6
|
import { Project } from "@opencode-ai/schema/project";
|
|
7
|
-
import { AbsolutePath,
|
|
7
|
+
import { AbsolutePath, PositiveInt, RelativePath, statics } from "@opencode-ai/schema/schema";
|
|
8
|
+
import { Event } from "@opencode-ai/schema/event";
|
|
8
9
|
import { Workspace } from "@opencode-ai/schema/workspace";
|
|
9
|
-
import { Context, Effect, Encoding, Result, Schema, Struct } from "effect";
|
|
10
|
+
import { Context, Effect, Encoding, Result, Schema, SchemaGetter, Struct } from "effect";
|
|
10
11
|
import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
|
|
11
12
|
import { ConflictError, CommandEvaluationError, CommandNotFoundError, InvalidCursorError, InvalidRequestError, MessageNotFoundError, ServiceUnavailableError, SessionBusyError, SessionNotFoundError, SkillNotFoundError, UnknownError, } from "../errors.js";
|
|
12
13
|
import { Agent } from "@opencode-ai/schema/agent";
|
|
@@ -14,6 +15,7 @@ import { Model } from "@opencode-ai/schema/model";
|
|
|
14
15
|
import { Location } from "@opencode-ai/schema/location";
|
|
15
16
|
import { Revert } from "@opencode-ai/schema/revert";
|
|
16
17
|
import { SessionEvent } from "@opencode-ai/schema/session-event";
|
|
18
|
+
import { EventLog } from "@opencode-ai/schema/event-log";
|
|
17
19
|
const SessionsQueryFields = {
|
|
18
20
|
workspace: Workspace.ID.pipe(Schema.optional),
|
|
19
21
|
limit: Schema.NumberFromString.pipe(Schema.decodeTo(PositiveInt), Schema.optional).annotate({
|
|
@@ -62,11 +64,14 @@ export const SessionsCursor = Schema.String.pipe(Schema.brand("SessionsCursor"),
|
|
|
62
64
|
const SessionActive = Schema.Struct({
|
|
63
65
|
type: Schema.Literal("running"),
|
|
64
66
|
}).annotate({ identifier: "SessionActive" });
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
after: Schema.NumberFromString.pipe(Schema.decodeTo(NonNegativeInt), Schema.optional),
|
|
67
|
+
const SessionWatermarks = Schema.Record(Session.ID, Event.Seq).annotate({
|
|
68
|
+
identifier: "SessionWatermarks",
|
|
69
|
+
description: "Durable log seq each session's snapshot was computed at. Attach a live log read after the watermark to compose fetch and stream gap-free; apply a snapshot only where its watermark is at or beyond already-applied events. Sessions without durable events are absent.",
|
|
69
70
|
});
|
|
71
|
+
const BooleanFromString = Schema.Literals(["true", "false"]).pipe(Schema.decodeTo(Schema.Boolean, {
|
|
72
|
+
decode: SchemaGetter.transform((value) => value === "true"),
|
|
73
|
+
encode: SchemaGetter.transform((value) => (value ? "true" : "false")),
|
|
74
|
+
}));
|
|
70
75
|
const SessionsQueryCursor = SessionsCursor.annotate({
|
|
71
76
|
description: "Opaque pagination cursor returned as cursor.previous or cursor.next in the previous response.",
|
|
72
77
|
});
|
|
@@ -82,6 +87,7 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
82
87
|
query: SessionsQuery,
|
|
83
88
|
success: Schema.Struct({
|
|
84
89
|
data: Schema.Array(Session.Info),
|
|
90
|
+
watermarks: SessionWatermarks,
|
|
85
91
|
cursor: Schema.Struct({
|
|
86
92
|
previous: SessionsCursor.pipe(Schema.optional),
|
|
87
93
|
next: SessionsCursor.pipe(Schema.optional),
|
|
@@ -107,11 +113,11 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
107
113
|
description: "Create a session at the requested location.",
|
|
108
114
|
})))
|
|
109
115
|
.add(HttpApiEndpoint.get("session.active", "/api/session/active", {
|
|
110
|
-
success: Schema.Struct({ data: Schema.Record(Session.ID, SessionActive) }),
|
|
116
|
+
success: Schema.Struct({ data: Schema.Record(Session.ID, SessionActive), watermarks: SessionWatermarks }),
|
|
111
117
|
}).annotateMerge(OpenApi.annotations({
|
|
112
118
|
identifier: "v2.session.active",
|
|
113
119
|
summary: "List active sessions",
|
|
114
|
-
description: "Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive.",
|
|
120
|
+
description: "Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive. Watermarks are the durable log positions read alongside the activity snapshot; activity itself is process state, so the pairing is advisory rather than transactional.",
|
|
115
121
|
})))
|
|
116
122
|
.add(HttpApiEndpoint.get("session.get", "/api/session/:sessionID", {
|
|
117
123
|
params: { sessionID: Session.ID },
|
|
@@ -336,34 +342,22 @@ export const makeSessionGroup = (sessionLocationMiddleware) => HttpApiGroup.make
|
|
|
336
342
|
summary: "Remove context entry",
|
|
337
343
|
description: "Remove one context entry; the removal is announced to the model at the next turn boundary.",
|
|
338
344
|
})))
|
|
339
|
-
.add(HttpApiEndpoint.get("session.
|
|
340
|
-
params: { sessionID: Session.ID },
|
|
341
|
-
query: SessionHistoryQuery,
|
|
342
|
-
success: Schema.Struct({
|
|
343
|
-
data: Schema.Array(SessionEvent.Durable),
|
|
344
|
-
hasMore: Schema.Boolean,
|
|
345
|
-
}).annotate({ identifier: "SessionHistory" }),
|
|
346
|
-
error: SessionNotFoundError,
|
|
347
|
-
})
|
|
348
|
-
.middleware(sessionLocationMiddleware)
|
|
349
|
-
.annotateMerge(OpenApi.annotations({
|
|
350
|
-
identifier: "v2.session.history",
|
|
351
|
-
summary: "Get session history",
|
|
352
|
-
description: "Read one finite page of public durable Session events after an exclusive aggregate sequence. Newly committed events may appear on later pages.",
|
|
353
|
-
})))
|
|
354
|
-
.add(HttpApiEndpoint.get("session.events", "/api/session/:sessionID/event", {
|
|
345
|
+
.add(HttpApiEndpoint.get("session.log", "/api/session/:sessionID/log", {
|
|
355
346
|
params: { sessionID: Session.ID },
|
|
356
347
|
query: {
|
|
357
|
-
after: Schema.NumberFromString.pipe(Schema.decodeTo(
|
|
348
|
+
after: Schema.NumberFromString.pipe(Schema.decodeTo(Event.Seq), Schema.optional),
|
|
349
|
+
follow: BooleanFromString.pipe(Schema.optional),
|
|
358
350
|
},
|
|
359
|
-
success: HttpApiSchema.StreamSse({
|
|
351
|
+
success: HttpApiSchema.StreamSse({
|
|
352
|
+
data: Schema.Union([SessionEvent.Durable, EventLog.CaughtUp]).annotate({ identifier: "SessionLogItem" }),
|
|
353
|
+
}),
|
|
360
354
|
error: SessionNotFoundError,
|
|
361
355
|
})
|
|
362
356
|
.middleware(sessionLocationMiddleware)
|
|
363
357
|
.annotateMerge(OpenApi.annotations({
|
|
364
|
-
identifier: "v2.session.
|
|
365
|
-
summary: "
|
|
366
|
-
description: "
|
|
358
|
+
identifier: "v2.session.log",
|
|
359
|
+
summary: "Read the session log",
|
|
360
|
+
description: "Durable, ordered, gap-free read of public session events after an exclusive aggregate sequence. Emits a caught-up marker once the replay reaches the end of the log, then completes; with follow=true it continues with live events instead. The only event API that promises reliability: attach after a snapshot watermark to compose fetch and stream without a race window.",
|
|
367
361
|
})))
|
|
368
362
|
.add(HttpApiEndpoint.post("session.interrupt", "/api/session/:sessionID/interrupt", {
|
|
369
363
|
params: { sessionID: Session.ID },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode-ai/protocol",
|
|
4
|
-
"version": "0.0.0-next-
|
|
4
|
+
"version": "0.0.0-next-14730",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"typecheck": "tsgo --noEmit"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@opencode-ai/schema": "0.0.0-next-
|
|
29
|
+
"@opencode-ai/schema": "0.0.0-next-14730",
|
|
30
30
|
"effect": "4.0.0-beta.83"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { Location } from "@opencode-ai/schema/location";
|
|
2
|
-
import { Context, Schema } from "effect";
|
|
3
|
-
import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema } from "effect/unstable/httpapi";
|
|
4
|
-
import { QuestionNotFoundError, SessionNotFoundError } from "../errors.js";
|
|
5
|
-
export declare const makeQuestionGroup: <LocationId extends HttpApiMiddleware.AnyId, LocationService, SessionLocationId extends HttpApiMiddleware.AnyId, SessionLocationService>(locationMiddleware: Context.Key<LocationId, LocationService>, sessionLocationMiddleware: Context.Key<SessionLocationId, SessionLocationService>) => HttpApiGroup.HttpApiGroup<"server.question", HttpApiEndpoint.HttpApiEndpoint<"question.request.list", "GET", "/api/question/request", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
6
|
-
readonly location: Schema.optional<Schema.Struct<{
|
|
7
|
-
readonly directory: Schema.optional<Schema.String>;
|
|
8
|
-
readonly workspace: Schema.optional<Schema.String>;
|
|
9
|
-
}>>;
|
|
10
|
-
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
11
|
-
readonly location: typeof Location.Info;
|
|
12
|
-
readonly data: Schema.$Array<Schema.Struct<{
|
|
13
|
-
readonly id: Schema.brand<Schema.String, "QuestionV2.ID"> & {
|
|
14
|
-
create: () => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
15
|
-
ascending: (id?: string) => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
16
|
-
};
|
|
17
|
-
readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
18
|
-
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
19
|
-
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
20
|
-
};
|
|
21
|
-
readonly questions: Schema.$Array<Schema.Struct<{
|
|
22
|
-
readonly custom: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
23
|
-
readonly question: Schema.String;
|
|
24
|
-
readonly header: Schema.String;
|
|
25
|
-
readonly options: Schema.$Array<Schema.Struct<{
|
|
26
|
-
readonly label: Schema.String;
|
|
27
|
-
readonly description: Schema.String;
|
|
28
|
-
}>>;
|
|
29
|
-
readonly multiple: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
30
|
-
}>>;
|
|
31
|
-
readonly tool: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Struct<{
|
|
32
|
-
readonly messageID: Schema.String;
|
|
33
|
-
readonly callID: Schema.String;
|
|
34
|
-
}>>>, Schema.optionalKey<Schema.Struct<{
|
|
35
|
-
readonly messageID: Schema.String;
|
|
36
|
-
readonly callID: Schema.String;
|
|
37
|
-
}>>, never, never>;
|
|
38
|
-
}>>;
|
|
39
|
-
}>>, HttpApiEndpoint.Json<never>, LocationId, HttpApiMiddleware.Requires<LocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.question.list", "GET", "/api/session/:sessionID/question", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
40
|
-
sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
41
|
-
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
42
|
-
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
43
|
-
};
|
|
44
|
-
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
45
|
-
readonly data: Schema.$Array<Schema.Struct<{
|
|
46
|
-
readonly id: Schema.brand<Schema.String, "QuestionV2.ID"> & {
|
|
47
|
-
create: () => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
48
|
-
ascending: (id?: string) => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
49
|
-
};
|
|
50
|
-
readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
51
|
-
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
52
|
-
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
53
|
-
};
|
|
54
|
-
readonly questions: Schema.$Array<Schema.Struct<{
|
|
55
|
-
readonly custom: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
56
|
-
readonly question: Schema.String;
|
|
57
|
-
readonly header: Schema.String;
|
|
58
|
-
readonly options: Schema.$Array<Schema.Struct<{
|
|
59
|
-
readonly label: Schema.String;
|
|
60
|
-
readonly description: Schema.String;
|
|
61
|
-
}>>;
|
|
62
|
-
readonly multiple: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
63
|
-
}>>;
|
|
64
|
-
readonly tool: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Struct<{
|
|
65
|
-
readonly messageID: Schema.String;
|
|
66
|
-
readonly callID: Schema.String;
|
|
67
|
-
}>>>, Schema.optionalKey<Schema.Struct<{
|
|
68
|
-
readonly messageID: Schema.String;
|
|
69
|
-
readonly callID: Schema.String;
|
|
70
|
-
}>>, never, never>;
|
|
71
|
-
}>>;
|
|
72
|
-
}>>, HttpApiEndpoint.Json<typeof SessionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.question.reply", "POST", "/api/session/:sessionID/question/:requestID/reply", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
73
|
-
sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
74
|
-
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
75
|
-
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
76
|
-
};
|
|
77
|
-
requestID: Schema.brand<Schema.String, "QuestionV2.ID"> & {
|
|
78
|
-
create: () => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
79
|
-
ascending: (id?: string) => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
80
|
-
};
|
|
81
|
-
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
82
|
-
readonly answers: Schema.$Array<Schema.$Array<Schema.String>>;
|
|
83
|
-
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof SessionNotFoundError | typeof QuestionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.question.reject", "POST", "/api/session/:sessionID/question/:requestID/reject", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
84
|
-
sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
85
|
-
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
86
|
-
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
87
|
-
};
|
|
88
|
-
requestID: Schema.brand<Schema.String, "QuestionV2.ID"> & {
|
|
89
|
-
create: () => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
90
|
-
ascending: (id?: string) => string & import("effect/Brand").Brand<"QuestionV2.ID">;
|
|
91
|
-
};
|
|
92
|
-
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof SessionNotFoundError | typeof QuestionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>>, false>;
|
package/dist/groups/question.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Question } from "@opencode-ai/schema/question";
|
|
2
|
-
import { Location } from "@opencode-ai/schema/location";
|
|
3
|
-
import { Session } from "@opencode-ai/schema/session";
|
|
4
|
-
import { Context, Schema } from "effect";
|
|
5
|
-
import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
|
|
6
|
-
import { QuestionNotFoundError, SessionNotFoundError } from "../errors.js";
|
|
7
|
-
import { LocationQuery, locationQueryOpenApi } from "./location.js";
|
|
8
|
-
export const makeQuestionGroup = (locationMiddleware, sessionLocationMiddleware) => HttpApiGroup.make("server.question")
|
|
9
|
-
.add(HttpApiEndpoint.get("question.request.list", "/api/question/request", {
|
|
10
|
-
query: LocationQuery,
|
|
11
|
-
success: Location.response(Schema.Array(Question.Request)),
|
|
12
|
-
})
|
|
13
|
-
.annotateMerge(locationQueryOpenApi)
|
|
14
|
-
.annotateMerge(OpenApi.annotations({
|
|
15
|
-
identifier: "v2.question.request.list",
|
|
16
|
-
summary: "List pending question requests",
|
|
17
|
-
description: "Retrieve pending question requests for a location.",
|
|
18
|
-
})))
|
|
19
|
-
.annotateMerge(OpenApi.annotations({ title: "questions", description: "Experimental question routes." }))
|
|
20
|
-
// Effect applies group middleware only to endpoints already added; session endpoints use session placement below.
|
|
21
|
-
.middleware(locationMiddleware)
|
|
22
|
-
.add(HttpApiEndpoint.get("session.question.list", "/api/session/:sessionID/question", {
|
|
23
|
-
params: { sessionID: Session.ID },
|
|
24
|
-
success: Schema.Struct({ data: Schema.Array(Question.Request) }),
|
|
25
|
-
error: SessionNotFoundError,
|
|
26
|
-
})
|
|
27
|
-
.middleware(sessionLocationMiddleware)
|
|
28
|
-
.annotateMerge(OpenApi.annotations({
|
|
29
|
-
identifier: "v2.session.question.list",
|
|
30
|
-
summary: "List session question requests",
|
|
31
|
-
description: "Retrieve pending question requests owned by a session.",
|
|
32
|
-
})))
|
|
33
|
-
.add(HttpApiEndpoint.post("session.question.reply", "/api/session/:sessionID/question/:requestID/reply", {
|
|
34
|
-
params: { sessionID: Session.ID, requestID: Question.ID },
|
|
35
|
-
payload: Question.Reply,
|
|
36
|
-
success: HttpApiSchema.NoContent,
|
|
37
|
-
error: [SessionNotFoundError, QuestionNotFoundError],
|
|
38
|
-
})
|
|
39
|
-
.middleware(sessionLocationMiddleware)
|
|
40
|
-
.annotateMerge(OpenApi.annotations({
|
|
41
|
-
identifier: "v2.session.question.reply",
|
|
42
|
-
summary: "Reply to pending question request",
|
|
43
|
-
description: "Answer a pending question request owned by a session.",
|
|
44
|
-
})))
|
|
45
|
-
.add(HttpApiEndpoint.post("session.question.reject", "/api/session/:sessionID/question/:requestID/reject", {
|
|
46
|
-
params: { sessionID: Session.ID, requestID: Question.ID },
|
|
47
|
-
success: HttpApiSchema.NoContent,
|
|
48
|
-
error: [SessionNotFoundError, QuestionNotFoundError],
|
|
49
|
-
})
|
|
50
|
-
.middleware(sessionLocationMiddleware)
|
|
51
|
-
.annotateMerge(OpenApi.annotations({
|
|
52
|
-
identifier: "v2.session.question.reject",
|
|
53
|
-
summary: "Reject pending question request",
|
|
54
|
-
description: "Reject a pending question request owned by a session.",
|
|
55
|
-
})))
|
|
56
|
-
.annotateMerge(OpenApi.annotations({ title: "session questions", description: "Experimental session question routes." }));
|