summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorShantur Rathore <[email protected]>2026-02-25 14:25:26 +0000
committerGitHub <[email protected]>2026-02-25 09:25:26 -0500
commit79b5ce58e9d3ad940330c2fd82784a4d8b7e004d (patch)
tree88500cdab6b0c28329ecca3c9e71fea8affe768c
parent088a81c116f3fda865851292c92754385292b92d (diff)
downloadopencode-79b5ce58e9d3ad940330c2fd82784a4d8b7e004d.tar.gz
opencode-79b5ce58e9d3ad940330c2fd82784a4d8b7e004d.zip
feat(core): add message delete endpoint (#14417)
-rw-r--r--packages/opencode/src/server/routes/session.ts36
-rw-r--r--packages/opencode/src/session/index.ts8
-rw-r--r--packages/sdk/js/src/v2/gen/sdk.gen.ts38
-rw-r--r--packages/sdk/js/src/v2/gen/types.gen.ts40
4 files changed, 120 insertions, 2 deletions
diff --git a/packages/opencode/src/server/routes/session.ts b/packages/opencode/src/server/routes/session.ts
index 1195529e0..12938aeab 100644
--- a/packages/opencode/src/server/routes/session.ts
+++ b/packages/opencode/src/server/routes/session.ts
@@ -619,6 +619,42 @@ export const SessionRoutes = lazy(() =>
},
)
.delete(
+ "/:sessionID/message/:messageID",
+ describeRoute({
+ summary: "Delete message",
+ description:
+ "Permanently delete a specific message (and all of its parts) from a session. This does not revert any file changes that may have been made while processing the message.",
+ operationId: "session.deleteMessage",
+ responses: {
+ 200: {
+ description: "Successfully deleted message",
+ content: {
+ "application/json": {
+ schema: resolver(z.boolean()),
+ },
+ },
+ },
+ ...errors(400, 404),
+ },
+ }),
+ validator(
+ "param",
+ z.object({
+ sessionID: z.string().meta({ description: "Session ID" }),
+ messageID: z.string().meta({ description: "Message ID" }),
+ }),
+ ),
+ async (c) => {
+ const params = c.req.valid("param")
+ SessionPrompt.assertNotBusy(params.sessionID)
+ await Session.removeMessage({
+ sessionID: params.sessionID,
+ messageID: params.messageID,
+ })
+ return c.json(true)
+ },
+ )
+ .delete(
"/:sessionID/message/:messageID/part/:partID",
describeRoute({
description: "Delete a part from a message",
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 8454a9c3e..22de477f8 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -697,7 +697,9 @@ export namespace Session {
async (input) => {
// CASCADE delete handles parts automatically
Database.use((db) => {
- db.delete(MessageTable).where(eq(MessageTable.id, input.messageID)).run()
+ db.delete(MessageTable)
+ .where(and(eq(MessageTable.id, input.messageID), eq(MessageTable.session_id, input.sessionID)))
+ .run()
Database.effect(() =>
Bus.publish(MessageV2.Event.Removed, {
sessionID: input.sessionID,
@@ -717,7 +719,9 @@ export namespace Session {
}),
async (input) => {
Database.use((db) => {
- db.delete(PartTable).where(eq(PartTable.id, input.partID)).run()
+ db.delete(PartTable)
+ .where(and(eq(PartTable.id, input.partID), eq(PartTable.session_id, input.sessionID)))
+ .run()
Database.effect(() =>
Bus.publish(MessageV2.Event.PartRemoved, {
sessionID: input.sessionID,
diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts
index b4848e605..6165c0f7b 100644
--- a/packages/sdk/js/src/v2/gen/sdk.gen.ts
+++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts
@@ -107,6 +107,8 @@ import type {
SessionCreateErrors,
SessionCreateResponses,
SessionDeleteErrors,
+ SessionDeleteMessageErrors,
+ SessionDeleteMessageResponses,
SessionDeleteResponses,
SessionDiffResponses,
SessionForkResponses,
@@ -1562,6 +1564,42 @@ export class Session2 extends HeyApiClient {
}
/**
+ * Delete message
+ *
+ * Permanently delete a specific message (and all of its parts) from a session. This does not revert any file changes that may have been made while processing the message.
+ */
+ public deleteMessage<ThrowOnError extends boolean = false>(
+ parameters: {
+ sessionID: string
+ messageID: string
+ directory?: string
+ },
+ options?: Options<never, ThrowOnError>,
+ ) {
+ const params = buildClientParams(
+ [parameters],
+ [
+ {
+ args: [
+ { in: "path", key: "sessionID" },
+ { in: "path", key: "messageID" },
+ { in: "query", key: "directory" },
+ ],
+ },
+ ],
+ )
+ return (options?.client ?? this.client).delete<
+ SessionDeleteMessageResponses,
+ SessionDeleteMessageErrors,
+ ThrowOnError
+ >({
+ url: "/session/{sessionID}/message/{messageID}",
+ ...options,
+ ...params,
+ })
+ }
+
+ /**
* Get message
*
* Retrieve a specific message from a session by its message ID.
diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts
index 4050ef157..28d5caa02 100644
--- a/packages/sdk/js/src/v2/gen/types.gen.ts
+++ b/packages/sdk/js/src/v2/gen/types.gen.ts
@@ -3564,6 +3564,46 @@ export type SessionPromptResponses = {
export type SessionPromptResponse = SessionPromptResponses[keyof SessionPromptResponses]
+export type SessionDeleteMessageData = {
+ body?: never
+ path: {
+ /**
+ * Session ID
+ */
+ sessionID: string
+ /**
+ * Message ID
+ */
+ messageID: string
+ }
+ query?: {
+ directory?: string
+ }
+ url: "/session/{sessionID}/message/{messageID}"
+}
+
+export type SessionDeleteMessageErrors = {
+ /**
+ * Bad request
+ */
+ 400: BadRequestError
+ /**
+ * Not found
+ */
+ 404: NotFoundError
+}
+
+export type SessionDeleteMessageError = SessionDeleteMessageErrors[keyof SessionDeleteMessageErrors]
+
+export type SessionDeleteMessageResponses = {
+ /**
+ * Successfully deleted message
+ */
+ 200: boolean
+}
+
+export type SessionDeleteMessageResponse = SessionDeleteMessageResponses[keyof SessionDeleteMessageResponses]
+
export type SessionMessageData = {
body?: never
path: {