Compare commits

...

5 Commits

Author SHA1 Message Date
Shoubhit Dash dde4988fde test: fix typed session ids 2026-03-12 10:52:55 +05:30
Shoubhit Dash 7a7632fc3d fix: preserve session history compat 2026-03-12 10:51:42 +05:30
Shoubhit Dash a894d1e11e fix: preserve session history compat 2026-03-12 10:51:42 +05:30
Shoubhit Dash 6381641833 chore: add migration snapshot 2026-03-12 10:51:14 +05:30
Shoubhit Dash c2641bc31d perf: paginate session history 2026-03-12 10:51:14 +05:30
10 changed files with 3042 additions and 363 deletions
@@ -0,0 +1,4 @@
DROP INDEX IF EXISTS `message_session_idx`;--> statement-breakpoint
DROP INDEX IF EXISTS `part_message_idx`;--> statement-breakpoint
CREATE INDEX `message_session_time_created_id_idx` ON `message` (`session_id`,`time_created`,`id`);--> statement-breakpoint
CREATE INDEX `part_message_id_id_idx` ON `part` (`message_id`,`id`);
@@ -0,0 +1,1226 @@
{
"version": "7",
"dialect": "sqlite",
"id": "37e1554d-af4c-43f2-aa7c-307fb49a315e",
"prevIds": [
"fb311f30-9948-4131-b15c-7d308478a878"
],
"ddl": [
{
"name": "account_state",
"entityType": "tables"
},
{
"name": "account",
"entityType": "tables"
},
{
"name": "control_account",
"entityType": "tables"
},
{
"name": "workspace",
"entityType": "tables"
},
{
"name": "project",
"entityType": "tables"
},
{
"name": "message",
"entityType": "tables"
},
{
"name": "part",
"entityType": "tables"
},
{
"name": "permission",
"entityType": "tables"
},
{
"name": "session",
"entityType": "tables"
},
{
"name": "todo",
"entityType": "tables"
},
{
"name": "session_share",
"entityType": "tables"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "account_state"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "active_account_id",
"entityType": "columns",
"table": "account_state"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "active_org_id",
"entityType": "columns",
"table": "account_state"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "email",
"entityType": "columns",
"table": "account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "url",
"entityType": "columns",
"table": "account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "access_token",
"entityType": "columns",
"table": "account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "refresh_token",
"entityType": "columns",
"table": "account"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "token_expiry",
"entityType": "columns",
"table": "account"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "account"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "email",
"entityType": "columns",
"table": "control_account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "url",
"entityType": "columns",
"table": "control_account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "access_token",
"entityType": "columns",
"table": "control_account"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "refresh_token",
"entityType": "columns",
"table": "control_account"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "token_expiry",
"entityType": "columns",
"table": "control_account"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "active",
"entityType": "columns",
"table": "control_account"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "control_account"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "control_account"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "type",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "branch",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "name",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "directory",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "extra",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "project_id",
"entityType": "columns",
"table": "workspace"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "worktree",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "vcs",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "name",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "icon_url",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "icon_color",
"entityType": "columns",
"table": "project"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "project"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "project"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_initialized",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "sandboxes",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "commands",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "message"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "session_id",
"entityType": "columns",
"table": "message"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "message"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "message"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "data",
"entityType": "columns",
"table": "message"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "part"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "message_id",
"entityType": "columns",
"table": "part"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "session_id",
"entityType": "columns",
"table": "part"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "part"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "part"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "data",
"entityType": "columns",
"table": "part"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "project_id",
"entityType": "columns",
"table": "permission"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "permission"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "permission"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "data",
"entityType": "columns",
"table": "permission"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "project_id",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "workspace_id",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "parent_id",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "slug",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "directory",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "title",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "version",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "share_url",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "summary_additions",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "summary_deletions",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "summary_files",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "summary_diffs",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "revert",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "permission",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_compacting",
"entityType": "columns",
"table": "session"
},
{
"type": "integer",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_archived",
"entityType": "columns",
"table": "session"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "session_id",
"entityType": "columns",
"table": "todo"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "content",
"entityType": "columns",
"table": "todo"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "status",
"entityType": "columns",
"table": "todo"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "priority",
"entityType": "columns",
"table": "todo"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "position",
"entityType": "columns",
"table": "todo"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "todo"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "todo"
},
{
"type": "text",
"notNull": false,
"autoincrement": false,
"default": null,
"generated": null,
"name": "session_id",
"entityType": "columns",
"table": "session_share"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "id",
"entityType": "columns",
"table": "session_share"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "secret",
"entityType": "columns",
"table": "session_share"
},
{
"type": "text",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "url",
"entityType": "columns",
"table": "session_share"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_created",
"entityType": "columns",
"table": "session_share"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": null,
"generated": null,
"name": "time_updated",
"entityType": "columns",
"table": "session_share"
},
{
"columns": [
"active_account_id"
],
"tableTo": "account",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "SET NULL",
"nameExplicit": false,
"name": "fk_account_state_active_account_id_account_id_fk",
"entityType": "fks",
"table": "account_state"
},
{
"columns": [
"project_id"
],
"tableTo": "project",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_workspace_project_id_project_id_fk",
"entityType": "fks",
"table": "workspace"
},
{
"columns": [
"session_id"
],
"tableTo": "session",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_message_session_id_session_id_fk",
"entityType": "fks",
"table": "message"
},
{
"columns": [
"message_id"
],
"tableTo": "message",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_part_message_id_message_id_fk",
"entityType": "fks",
"table": "part"
},
{
"columns": [
"project_id"
],
"tableTo": "project",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_permission_project_id_project_id_fk",
"entityType": "fks",
"table": "permission"
},
{
"columns": [
"project_id"
],
"tableTo": "project",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_session_project_id_project_id_fk",
"entityType": "fks",
"table": "session"
},
{
"columns": [
"session_id"
],
"tableTo": "session",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_todo_session_id_session_id_fk",
"entityType": "fks",
"table": "todo"
},
{
"columns": [
"session_id"
],
"tableTo": "session",
"columnsTo": [
"id"
],
"onUpdate": "NO ACTION",
"onDelete": "CASCADE",
"nameExplicit": false,
"name": "fk_session_share_session_id_session_id_fk",
"entityType": "fks",
"table": "session_share"
},
{
"columns": [
"email",
"url"
],
"nameExplicit": false,
"name": "control_account_pk",
"entityType": "pks",
"table": "control_account"
},
{
"columns": [
"session_id",
"position"
],
"nameExplicit": false,
"name": "todo_pk",
"entityType": "pks",
"table": "todo"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "account_state_pk",
"table": "account_state",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "account_pk",
"table": "account",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "workspace_pk",
"table": "workspace",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "project_pk",
"table": "project",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "message_pk",
"table": "message",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "part_pk",
"table": "part",
"entityType": "pks"
},
{
"columns": [
"project_id"
],
"nameExplicit": false,
"name": "permission_pk",
"table": "permission",
"entityType": "pks"
},
{
"columns": [
"id"
],
"nameExplicit": false,
"name": "session_pk",
"table": "session",
"entityType": "pks"
},
{
"columns": [
"session_id"
],
"nameExplicit": false,
"name": "session_share_pk",
"table": "session_share",
"entityType": "pks"
},
{
"columns": [
{
"value": "session_id",
"isExpression": false
},
{
"value": "time_created",
"isExpression": false
},
{
"value": "id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "message_session_time_created_id_idx",
"entityType": "indexes",
"table": "message"
},
{
"columns": [
{
"value": "message_id",
"isExpression": false
},
{
"value": "id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "part_message_id_id_idx",
"entityType": "indexes",
"table": "part"
},
{
"columns": [
{
"value": "session_id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "part_session_idx",
"entityType": "indexes",
"table": "part"
},
{
"columns": [
{
"value": "project_id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "session_project_idx",
"entityType": "indexes",
"table": "session"
},
{
"columns": [
{
"value": "workspace_id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "session_workspace_idx",
"entityType": "indexes",
"table": "session"
},
{
"columns": [
{
"value": "parent_id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "session_parent_idx",
"entityType": "indexes",
"table": "session"
},
{
"columns": [
{
"value": "session_id",
"isExpression": false
}
],
"isUnique": false,
"where": null,
"origin": "manual",
"name": "todo_session_idx",
"entityType": "indexes",
"table": "todo"
}
],
"renames": []
}
+54 -6
View File
@@ -568,17 +568,65 @@ export const SessionRoutes = lazy(() =>
),
validator(
"query",
z.object({
limit: z.coerce.number().optional(),
}),
z
.object({
limit: z.coerce
.number()
.int()
.min(0)
.optional()
.meta({ description: "Maximum number of messages to return" }),
before: z
.string()
.optional()
.meta({ description: "Opaque cursor for loading older messages" })
.refine(
(value) => {
if (!value) return true
try {
MessageV2.cursor.decode(value)
return true
} catch {
return false
}
},
{ message: "Invalid cursor" },
),
})
.refine((value) => !value.before || value.limit !== undefined, {
message: "before requires limit",
path: ["before"],
}),
),
async (c) => {
const query = c.req.valid("query")
const messages = await Session.messages({
sessionID: c.req.valid("param").sessionID,
const sessionID = c.req.valid("param").sessionID
if (query.limit === undefined) {
await Session.get(sessionID)
const messages = await Session.messages({ sessionID })
return c.json(messages)
}
if (query.limit === 0) {
await Session.get(sessionID)
const messages = await Session.messages({ sessionID })
return c.json(messages)
}
const page = await MessageV2.page({
sessionID,
limit: query.limit,
before: query.before,
})
return c.json(messages)
if (page.cursor) {
const url = new URL(c.req.url)
url.searchParams.set("limit", query.limit.toString())
url.searchParams.set("before", page.cursor)
c.header("Access-Control-Expose-Headers", "Link, X-Next-Cursor")
c.header("Link", `<${url.toString()}>; rel=\"next\"`)
c.header("X-Next-Cursor", page.cursor)
}
return c.json(page.items)
},
)
.get(
+116 -44
View File
@@ -6,8 +6,8 @@ import { APICallError, convertToModelMessages, LoadAPIKeyError, type ModelMessag
import { LSP } from "../lsp"
import { Snapshot } from "@/snapshot"
import { fn } from "@/util/fn"
import { Database, eq, desc, inArray } from "@/storage/db"
import { MessageTable, PartTable } from "./session.sql"
import { Database, NotFoundError, and, desc, eq, inArray, lt, or } from "@/storage/db"
import { MessageTable, PartTable, SessionTable } from "./session.sql"
import { ProviderTransform } from "@/provider/transform"
import { STATUS_CODES } from "http"
import { Storage } from "@/storage/storage"
@@ -493,6 +493,68 @@ export namespace MessageV2 {
})
export type WithParts = z.infer<typeof WithParts>
const Cursor = z.object({
id: MessageID.zod,
time: z.number(),
})
type Cursor = z.infer<typeof Cursor>
export const cursor = {
encode(input: Cursor) {
return Buffer.from(JSON.stringify(input)).toString("base64url")
},
decode(input: string) {
return Cursor.parse(JSON.parse(Buffer.from(input, "base64url").toString("utf8")))
},
}
const info = (row: typeof MessageTable.$inferSelect) =>
({
...row.data,
id: row.id,
sessionID: row.session_id,
}) as MessageV2.Info
const part = (row: typeof PartTable.$inferSelect) =>
({
...row.data,
id: row.id,
sessionID: row.session_id,
messageID: row.message_id,
}) as MessageV2.Part
const older = (row: Cursor) =>
or(
lt(MessageTable.time_created, row.time),
and(eq(MessageTable.time_created, row.time), lt(MessageTable.id, row.id)),
)
async function hydrate(rows: (typeof MessageTable.$inferSelect)[]) {
const ids = rows.map((row) => row.id)
const partByMessage = new Map<string, MessageV2.Part[]>()
if (ids.length > 0) {
const partRows = Database.use((db) =>
db
.select()
.from(PartTable)
.where(inArray(PartTable.message_id, ids))
.orderBy(PartTable.message_id, PartTable.id)
.all(),
)
for (const row of partRows) {
const next = part(row)
const list = partByMessage.get(row.message_id)
if (list) list.push(next)
else partByMessage.set(row.message_id, [next])
}
}
return rows.map((row) => ({
info: info(row),
parts: partByMessage.get(row.id) ?? [],
}))
}
export function toModelMessages(
input: WithParts[],
model: Provider.Model,
@@ -728,56 +790,61 @@ export namespace MessageV2 {
)
}
export const stream = fn(SessionID.zod, async function* (sessionID) {
const size = 50
let offset = 0
while (true) {
export const page = fn(
z.object({
sessionID: SessionID.zod,
limit: z.number().int().positive(),
before: z.string().optional(),
}),
async (input) => {
const before = input.before ? cursor.decode(input.before) : undefined
const where = before
? and(eq(MessageTable.session_id, input.sessionID), older(before))
: eq(MessageTable.session_id, input.sessionID)
const rows = Database.use((db) =>
db
.select()
.from(MessageTable)
.where(eq(MessageTable.session_id, sessionID))
.orderBy(desc(MessageTable.time_created))
.limit(size)
.offset(offset)
.where(where)
.orderBy(desc(MessageTable.time_created), desc(MessageTable.id))
.limit(input.limit + 1)
.all(),
)
if (rows.length === 0) break
const ids = rows.map((row) => row.id)
const partsByMessage = new Map<string, MessageV2.Part[]>()
if (ids.length > 0) {
const partRows = Database.use((db) =>
db
.select()
.from(PartTable)
.where(inArray(PartTable.message_id, ids))
.orderBy(PartTable.message_id, PartTable.id)
.all(),
if (rows.length === 0) {
const row = Database.use((db) =>
db.select({ id: SessionTable.id }).from(SessionTable).where(eq(SessionTable.id, input.sessionID)).get(),
)
for (const row of partRows) {
const part = {
...row.data,
id: row.id,
sessionID: row.session_id,
messageID: row.message_id,
} as MessageV2.Part
const list = partsByMessage.get(row.message_id)
if (list) list.push(part)
else partsByMessage.set(row.message_id, [part])
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
return {
items: [] as MessageV2.WithParts[],
more: false,
}
}
for (const row of rows) {
const info = { ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info
yield {
info,
parts: partsByMessage.get(row.id) ?? [],
}
const more = rows.length > input.limit
const page = more ? rows.slice(0, input.limit) : rows
const items = await hydrate(page)
items.reverse()
const tail = page.at(-1)
return {
items,
more,
cursor: more && tail ? cursor.encode({ id: tail.id, time: tail.time_created }) : undefined,
}
},
)
offset += rows.length
if (rows.length < size) break
export const stream = fn(SessionID.zod, async function* (sessionID) {
const size = 50
let before: string | undefined
while (true) {
const next = await page({ sessionID, limit: size, before })
if (next.items.length === 0) break
for (let i = next.items.length - 1; i >= 0; i--) {
yield next.items[i]
}
if (!next.more || !next.cursor) break
before = next.cursor
}
})
@@ -796,11 +863,16 @@ export namespace MessageV2 {
messageID: MessageID.zod,
}),
async (input): Promise<WithParts> => {
const row = Database.use((db) => db.select().from(MessageTable).where(eq(MessageTable.id, input.messageID)).get())
if (!row) throw new Error(`Message not found: ${input.messageID}`)
const info = { ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info
const row = Database.use((db) =>
db
.select()
.from(MessageTable)
.where(and(eq(MessageTable.id, input.messageID), eq(MessageTable.session_id, input.sessionID)))
.get(),
)
if (!row) throw new NotFoundError({ message: `Message not found: ${input.messageID}` })
return {
info,
info: info(row),
parts: await parts(input.messageID),
}
},
+5 -2
View File
@@ -54,7 +54,7 @@ export const MessageTable = sqliteTable(
...Timestamps,
data: text({ mode: "json" }).notNull().$type<InfoData>(),
},
(table) => [index("message_session_idx").on(table.session_id)],
(table) => [index("message_session_time_created_id_idx").on(table.session_id, table.time_created, table.id)],
)
export const PartTable = sqliteTable(
@@ -69,7 +69,10 @@ export const PartTable = sqliteTable(
...Timestamps,
data: text({ mode: "json" }).notNull().$type<PartData>(),
},
(table) => [index("part_message_idx").on(table.message_id), index("part_session_idx").on(table.session_id)],
(table) => [
index("part_message_id_id_idx").on(table.message_id, table.id),
index("part_session_idx").on(table.session_id),
],
)
export const TodoTable = sqliteTable(
@@ -0,0 +1,119 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { Instance } from "../../src/project/instance"
import { Server } from "../../src/server/server"
import { Session } from "../../src/session"
import { MessageV2 } from "../../src/session/message-v2"
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
import { Log } from "../../src/util/log"
const root = path.join(__dirname, "../..")
Log.init({ print: false })
async function fill(sessionID: SessionID, count: number, time = (i: number) => Date.now() + i) {
const ids = [] as MessageID[]
for (let i = 0; i < count; i++) {
const id = MessageID.ascending()
ids.push(id)
await Session.updateMessage({
id,
sessionID,
role: "user",
time: { created: time(i) },
agent: "test",
model: { providerID: "test", modelID: "test" },
tools: {},
mode: "",
} as unknown as MessageV2.Info)
await Session.updatePart({
id: PartID.ascending(),
sessionID,
messageID: id,
type: "text",
text: `m${i}`,
})
}
return ids
}
describe("session messages endpoint", () => {
test("returns cursor headers for older pages", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const ids = await fill(session.id, 5)
const app = Server.Default()
const a = await app.request(`/session/${session.id}/message?limit=2`)
expect(a.status).toBe(200)
const aBody = (await a.json()) as MessageV2.WithParts[]
expect(aBody.map((item) => item.info.id)).toEqual(ids.slice(-2))
const cursor = a.headers.get("x-next-cursor")
expect(cursor).toBeTruthy()
expect(a.headers.get("link")).toContain('rel="next"')
const b = await app.request(`/session/${session.id}/message?limit=2&before=${encodeURIComponent(cursor!)}`)
expect(b.status).toBe(200)
const bBody = (await b.json()) as MessageV2.WithParts[]
expect(bBody.map((item) => item.info.id)).toEqual(ids.slice(-4, -2))
await Session.remove(session.id)
},
})
})
test("keeps full-history responses when limit is omitted", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const ids = await fill(session.id, 3)
const app = Server.Default()
const res = await app.request(`/session/${session.id}/message`)
expect(res.status).toBe(200)
const body = (await res.json()) as MessageV2.WithParts[]
expect(body.map((item) => item.info.id)).toEqual(ids)
await Session.remove(session.id)
},
})
})
test("rejects invalid cursors and missing sessions", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const app = Server.Default()
const bad = await app.request(`/session/${session.id}/message?limit=2&before=bad`)
expect(bad.status).toBe(400)
const miss = await app.request(`/session/ses_missing/message?limit=2`)
expect(miss.status).toBe(404)
await Session.remove(session.id)
},
})
})
test("does not truncate large legacy limit requests", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
await fill(session.id, 520)
const app = Server.Default()
const res = await app.request(`/session/${session.id}/message?limit=510`)
expect(res.status).toBe(200)
const body = (await res.json()) as MessageV2.WithParts[]
expect(body).toHaveLength(510)
await Session.remove(session.id)
},
})
})
})
@@ -0,0 +1,115 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { Instance } from "../../src/project/instance"
import { Session } from "../../src/session"
import { MessageV2 } from "../../src/session/message-v2"
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
import { Log } from "../../src/util/log"
const root = path.join(__dirname, "../..")
Log.init({ print: false })
async function fill(sessionID: SessionID, count: number, time = (i: number) => Date.now() + i) {
const ids = [] as MessageID[]
for (let i = 0; i < count; i++) {
const id = MessageID.ascending()
ids.push(id)
await Session.updateMessage({
id,
sessionID,
role: "user",
time: { created: time(i) },
agent: "test",
model: { providerID: "test", modelID: "test" },
tools: {},
mode: "",
} as unknown as MessageV2.Info)
await Session.updatePart({
id: PartID.ascending(),
sessionID,
messageID: id,
type: "text",
text: `m${i}`,
})
}
return ids
}
describe("session message pagination", () => {
test("pages backward with opaque cursors", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const ids = await fill(session.id, 6)
const a = await MessageV2.page({ sessionID: session.id, limit: 2 })
expect(a.items.map((item) => item.info.id)).toEqual(ids.slice(-2))
expect(a.items.every((item) => item.parts.length === 1)).toBe(true)
expect(a.more).toBe(true)
expect(a.cursor).toBeTruthy()
const b = await MessageV2.page({ sessionID: session.id, limit: 2, before: a.cursor! })
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(-4, -2))
expect(b.more).toBe(true)
expect(b.cursor).toBeTruthy()
const c = await MessageV2.page({ sessionID: session.id, limit: 2, before: b.cursor! })
expect(c.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
expect(c.more).toBe(false)
expect(c.cursor).toBeUndefined()
await Session.remove(session.id)
},
})
})
test("keeps stream order newest first", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const ids = await fill(session.id, 5)
const items = await Array.fromAsync(MessageV2.stream(session.id))
expect(items.map((item) => item.info.id)).toEqual(ids.slice().reverse())
await Session.remove(session.id)
},
})
})
test("accepts cursors generated from fractional timestamps", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const session = await Session.create({})
const ids = await fill(session.id, 4, (i) => 1000.5 + i)
const a = await MessageV2.page({ sessionID: session.id, limit: 2 })
const b = await MessageV2.page({ sessionID: session.id, limit: 2, before: a.cursor! })
expect(a.items.map((item) => item.info.id)).toEqual(ids.slice(-2))
expect(b.items.map((item) => item.info.id)).toEqual(ids.slice(0, 2))
await Session.remove(session.id)
},
})
})
test("scopes get by session id", async () => {
await Instance.provide({
directory: root,
fn: async () => {
const a = await Session.create({})
const b = await Session.create({})
const [id] = await fill(a.id, 1)
await expect(MessageV2.get({ sessionID: b.id, messageID: id })).rejects.toMatchObject({ name: "NotFoundError" })
await Session.remove(a.id)
await Session.remove(b.id)
},
})
})
})
+2
View File
@@ -1793,6 +1793,7 @@ export class Session2 extends HeyApiClient {
directory?: string
workspace?: string
limit?: number
before?: string
},
options?: Options<never, ThrowOnError>,
) {
@@ -1805,6 +1806,7 @@ export class Session2 extends HeyApiClient {
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
{ in: "query", key: "limit" },
{ in: "query", key: "before" },
],
},
],
+4
View File
@@ -3232,7 +3232,11 @@ export type SessionMessagesData = {
query?: {
directory?: string
workspace?: string
/**
* Maximum number of messages to return
*/
limit?: number
before?: string
}
url: "/session/{sessionID}/message"
}
+1397 -311
View File
@@ -27,7 +27,10 @@
"type": "string"
}
},
"required": ["healthy", "version"]
"required": [
"healthy",
"version"
]
}
}
}
@@ -744,7 +747,10 @@
"type": "number"
}
},
"required": ["rows", "cols"]
"required": [
"rows",
"cols"
]
}
}
}
@@ -1021,7 +1027,10 @@
}
}
},
"required": ["providers", "default"]
"required": [
"providers",
"default"
]
}
}
}
@@ -1228,7 +1237,11 @@
]
}
},
"required": ["type", "branch", "extra"]
"required": [
"type",
"branch",
"extra"
]
}
}
}
@@ -1941,7 +1954,9 @@
],
"summary": "Get session",
"description": "Retrieve detailed information about a specific OpenCode session.",
"tags": ["Session"],
"tags": [
"Session"
],
"responses": {
"200": {
"description": "Get session",
@@ -2169,7 +2184,9 @@
}
],
"summary": "Get session children",
"tags": ["Session"],
"tags": [
"Session"
],
"description": "Retrieve all child sessions that were forked from the specified parent session.",
"responses": {
"200": {
@@ -2366,7 +2383,11 @@
"pattern": "^msg.*"
}
},
"required": ["modelID", "providerID", "messageID"]
"required": [
"modelID",
"providerID",
"messageID"
]
}
}
}
@@ -2792,7 +2813,10 @@
"type": "boolean"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
}
}
}
@@ -2836,7 +2860,17 @@
"in": "query",
"name": "limit",
"schema": {
"type": "number"
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"description": "Maximum number of messages to return"
},
{
"in": "query",
"name": "before",
"schema": {
"type": "string"
}
}
],
@@ -2862,7 +2896,10 @@
}
}
},
"required": ["info", "parts"]
"required": [
"info",
"parts"
]
}
}
}
@@ -2943,7 +2980,10 @@
}
}
},
"required": ["info", "parts"]
"required": [
"info",
"parts"
]
}
}
}
@@ -2989,7 +3029,10 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"agent": {
"type": "string"
@@ -3036,7 +3079,9 @@
}
}
},
"required": ["parts"]
"required": [
"parts"
]
}
}
}
@@ -3106,7 +3151,10 @@
}
}
},
"required": ["info", "parts"]
"required": [
"info",
"parts"
]
}
}
}
@@ -3473,7 +3521,10 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"agent": {
"type": "string"
@@ -3520,7 +3571,9 @@
}
}
},
"required": ["parts"]
"required": [
"parts"
]
}
}
}
@@ -3581,7 +3634,10 @@
}
}
},
"required": ["info", "parts"]
"required": [
"info",
"parts"
]
}
}
}
@@ -3660,13 +3716,20 @@
"$ref": "#/components/schemas/FilePartSource"
}
},
"required": ["type", "mime", "url"]
"required": [
"type",
"mime",
"url"
]
}
]
}
}
},
"required": ["arguments", "command"]
"required": [
"arguments",
"command"
]
}
}
}
@@ -3760,13 +3823,19 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"command": {
"type": "string"
}
},
"required": ["agent", "command"]
"required": [
"agent",
"command"
]
}
}
}
@@ -3856,7 +3925,9 @@
"pattern": "^prt.*"
}
},
"required": ["messageID"]
"required": [
"messageID"
]
}
}
}
@@ -4019,10 +4090,16 @@
"properties": {
"response": {
"type": "string",
"enum": ["once", "always", "reject"]
"enum": [
"once",
"always",
"reject"
]
}
},
"required": ["response"]
"required": [
"response"
]
}
}
}
@@ -4105,13 +4182,19 @@
"properties": {
"reply": {
"type": "string",
"enum": ["once", "always", "reject"]
"enum": [
"once",
"always",
"reject"
]
},
"message": {
"type": "string"
}
},
"required": ["reply"]
"required": [
"reply"
]
}
}
}
@@ -4288,7 +4371,9 @@
}
}
},
"required": ["answers"]
"required": [
"answers"
]
}
}
}
@@ -4466,10 +4551,15 @@
"properties": {
"field": {
"type": "string",
"enum": ["reasoning_content", "reasoning_details"]
"enum": [
"reasoning_content",
"reasoning_details"
]
}
},
"required": ["field"],
"required": [
"field"
],
"additionalProperties": false
}
]
@@ -4505,10 +4595,16 @@
"type": "number"
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"limit": {
"type": "object",
@@ -4523,7 +4619,10 @@
"type": "number"
}
},
"required": ["context", "output"]
"required": [
"context",
"output"
]
},
"modalities": {
"type": "object",
@@ -4532,25 +4631,44 @@
"type": "array",
"items": {
"type": "string",
"enum": ["text", "audio", "image", "video", "pdf"]
"enum": [
"text",
"audio",
"image",
"video",
"pdf"
]
}
},
"output": {
"type": "array",
"items": {
"type": "string",
"enum": ["text", "audio", "image", "video", "pdf"]
"enum": [
"text",
"audio",
"image",
"video",
"pdf"
]
}
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"experimental": {
"type": "boolean"
},
"status": {
"type": "string",
"enum": ["alpha", "beta", "deprecated"]
"enum": [
"alpha",
"beta",
"deprecated"
]
},
"options": {
"type": "object",
@@ -4607,7 +4725,12 @@
}
}
},
"required": ["name", "env", "id", "models"]
"required": [
"name",
"env",
"id",
"models"
]
}
},
"default": {
@@ -4626,7 +4749,11 @@
}
}
},
"required": ["all", "default", "connected"]
"required": [
"all",
"default",
"connected"
]
}
}
}
@@ -4753,7 +4880,9 @@
"type": "number"
}
},
"required": ["method"]
"required": [
"method"
]
}
}
}
@@ -4833,7 +4962,9 @@
"type": "string"
}
},
"required": ["method"]
"required": [
"method"
]
}
}
}
@@ -4892,7 +5023,9 @@
"type": "string"
}
},
"required": ["text"]
"required": [
"text"
]
},
"lines": {
"type": "object",
@@ -4901,7 +5034,9 @@
"type": "string"
}
},
"required": ["text"]
"required": [
"text"
]
},
"line_number": {
"type": "number"
@@ -4921,7 +5056,9 @@
"type": "string"
}
},
"required": ["text"]
"required": [
"text"
]
},
"start": {
"type": "number"
@@ -4930,11 +5067,21 @@
"type": "number"
}
},
"required": ["match", "start", "end"]
"required": [
"match",
"start",
"end"
]
}
}
},
"required": ["path", "lines", "line_number", "absolute_offset", "submatches"]
"required": [
"path",
"lines",
"line_number",
"absolute_offset",
"submatches"
]
}
}
}
@@ -4980,7 +5127,10 @@
"name": "dirs",
"schema": {
"type": "string",
"enum": ["true", "false"]
"enum": [
"true",
"false"
]
}
},
{
@@ -4988,7 +5138,10 @@
"name": "type",
"schema": {
"type": "string",
"enum": ["file", "directory"]
"enum": [
"file",
"directory"
]
}
},
{
@@ -5337,7 +5490,10 @@
]
}
},
"required": ["name", "config"]
"required": [
"name",
"config"
]
}
}
}
@@ -5392,7 +5548,9 @@
"type": "string"
}
},
"required": ["authorizationUrl"]
"required": [
"authorizationUrl"
]
}
}
}
@@ -5466,7 +5624,9 @@
"const": true
}
},
"required": ["success"]
"required": [
"success"
]
}
}
}
@@ -5562,7 +5722,9 @@
"type": "string"
}
},
"required": ["code"]
"required": [
"code"
]
}
}
}
@@ -5793,7 +5955,9 @@
"type": "string"
}
},
"required": ["text"]
"required": [
"text"
]
}
}
}
@@ -6105,7 +6269,9 @@
"type": "string"
}
},
"required": ["command"]
"required": [
"command"
]
}
}
}
@@ -6165,7 +6331,12 @@
},
"variant": {
"type": "string",
"enum": ["info", "success", "warning", "error"]
"enum": [
"info",
"success",
"warning",
"error"
]
},
"duration": {
"description": "Duration in milliseconds",
@@ -6173,7 +6344,10 @@
"type": "number"
}
},
"required": ["message", "variant"]
"required": [
"message",
"variant"
]
}
}
}
@@ -6324,7 +6498,9 @@
"pattern": "^ses.*"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@@ -6371,7 +6547,10 @@
},
"body": {}
},
"required": ["path", "body"]
"required": [
"path",
"body"
]
}
}
}
@@ -6656,7 +6835,12 @@
"level": {
"description": "Log level",
"type": "string",
"enum": ["debug", "info", "error", "warn"]
"enum": [
"debug",
"info",
"error",
"warn"
]
},
"message": {
"description": "Log message",
@@ -6671,7 +6855,11 @@
"additionalProperties": {}
}
},
"required": ["service", "level", "message"]
"required": [
"service",
"level",
"message"
]
}
}
}
@@ -6772,7 +6960,12 @@
"type": "string"
}
},
"required": ["name", "description", "location", "content"]
"required": [
"name",
"description",
"location",
"content"
]
}
}
}
@@ -6933,10 +7126,15 @@
"type": "string"
}
},
"required": ["version"]
"required": [
"version"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.installation.update-available": {
"type": "object",
@@ -6952,10 +7150,15 @@
"type": "string"
}
},
"required": ["version"]
"required": [
"version"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Project": {
"type": "object",
@@ -7009,7 +7212,10 @@
"type": "number"
}
},
"required": ["created", "updated"]
"required": [
"created",
"updated"
]
},
"sandboxes": {
"type": "array",
@@ -7018,7 +7224,12 @@
}
}
},
"required": ["id", "worktree", "time", "sandboxes"]
"required": [
"id",
"worktree",
"time",
"sandboxes"
]
},
"Event.project.updated": {
"type": "object",
@@ -7031,7 +7242,10 @@
"$ref": "#/components/schemas/Project"
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.server.instance.disposed": {
"type": "object",
@@ -7047,10 +7261,15 @@
"type": "string"
}
},
"required": ["directory"]
"required": [
"directory"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.server.connected": {
"type": "object",
@@ -7064,7 +7283,10 @@
"properties": {}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.global.disposed": {
"type": "object",
@@ -7078,7 +7300,10 @@
"properties": {}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.lsp.client.diagnostics": {
"type": "object",
@@ -7097,10 +7322,16 @@
"type": "string"
}
},
"required": ["serverID", "path"]
"required": [
"serverID",
"path"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.lsp.updated": {
"type": "object",
@@ -7114,7 +7345,10 @@
"properties": {}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.file.edited": {
"type": "object",
@@ -7130,10 +7364,15 @@
"type": "string"
}
},
"required": ["file"]
"required": [
"file"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"OutputFormatText": {
"type": "object",
@@ -7143,7 +7382,9 @@
"const": "text"
}
},
"required": ["type"]
"required": [
"type"
]
},
"JSONSchema": {
"type": "object",
@@ -7169,7 +7410,10 @@
"maximum": 9007199254740991
}
},
"required": ["type", "schema"]
"required": [
"type",
"schema"
]
},
"OutputFormat": {
"anyOf": [
@@ -7201,10 +7445,20 @@
},
"status": {
"type": "string",
"enum": ["added", "deleted", "modified"]
"enum": [
"added",
"deleted",
"modified"
]
}
},
"required": ["file", "before", "after", "additions", "deletions"]
"required": [
"file",
"before",
"after",
"additions",
"deletions"
]
},
"UserMessage": {
"type": "object",
@@ -7228,7 +7482,9 @@
"type": "number"
}
},
"required": ["created"]
"required": [
"created"
]
},
"format": {
"$ref": "#/components/schemas/OutputFormat"
@@ -7249,7 +7505,9 @@
}
}
},
"required": ["diffs"]
"required": [
"diffs"
]
},
"agent": {
"type": "string"
@@ -7264,7 +7522,10 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"system": {
"type": "string"
@@ -7282,7 +7543,14 @@
"type": "string"
}
},
"required": ["id", "sessionID", "role", "time", "agent", "model"]
"required": [
"id",
"sessionID",
"role",
"time",
"agent",
"model"
]
},
"ProviderAuthError": {
"type": "object",
@@ -7301,10 +7569,16 @@
"type": "string"
}
},
"required": ["providerID", "message"]
"required": [
"providerID",
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"UnknownError": {
"type": "object",
@@ -7320,10 +7594,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"MessageOutputLengthError": {
"type": "object",
@@ -7337,7 +7616,10 @@
"properties": {}
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"MessageAbortedError": {
"type": "object",
@@ -7353,10 +7635,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"StructuredOutputError": {
"type": "object",
@@ -7375,10 +7662,16 @@
"type": "number"
}
},
"required": ["message", "retries"]
"required": [
"message",
"retries"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"ContextOverflowError": {
"type": "object",
@@ -7397,10 +7690,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"APIError": {
"type": "object",
@@ -7443,10 +7741,16 @@
}
}
},
"required": ["message", "isRetryable"]
"required": [
"message",
"isRetryable"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"AssistantMessage": {
"type": "object",
@@ -7473,7 +7777,9 @@
"type": "number"
}
},
"required": ["created"]
"required": [
"created"
]
},
"error": {
"anyOf": [
@@ -7526,7 +7832,10 @@
"type": "string"
}
},
"required": ["cwd", "root"]
"required": [
"cwd",
"root"
]
},
"summary": {
"type": "boolean"
@@ -7559,10 +7868,18 @@
"type": "number"
}
},
"required": ["read", "write"]
"required": [
"read",
"write"
]
}
},
"required": ["input", "output", "reasoning", "cache"]
"required": [
"input",
"output",
"reasoning",
"cache"
]
},
"structured": {},
"variant": {
@@ -7611,10 +7928,15 @@
"$ref": "#/components/schemas/Message"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.message.removed": {
"type": "object",
@@ -7635,10 +7957,16 @@
"pattern": "^msg.*"
}
},
"required": ["sessionID", "messageID"]
"required": [
"sessionID",
"messageID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"TextPart": {
"type": "object",
@@ -7678,7 +8006,9 @@
"type": "number"
}
},
"required": ["start"]
"required": [
"start"
]
},
"metadata": {
"type": "object",
@@ -7688,7 +8018,13 @@
"additionalProperties": {}
}
},
"required": ["id", "sessionID", "messageID", "type", "text"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"text"
]
},
"SubtaskPart": {
"type": "object",
@@ -7728,13 +8064,24 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"command": {
"type": "string"
}
},
"required": ["id", "sessionID", "messageID", "type", "prompt", "description", "agent"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"prompt",
"description",
"agent"
]
},
"ReasoningPart": {
"type": "object",
@@ -7775,10 +8122,19 @@
"type": "number"
}
},
"required": ["start"]
"required": [
"start"
]
}
},
"required": ["id", "sessionID", "messageID", "type", "text", "time"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"text",
"time"
]
},
"FilePartSourceText": {
"type": "object",
@@ -7797,7 +8153,11 @@
"maximum": 9007199254740991
}
},
"required": ["value", "start", "end"]
"required": [
"value",
"start",
"end"
]
},
"FileSource": {
"type": "object",
@@ -7813,7 +8173,11 @@
"type": "string"
}
},
"required": ["text", "type", "path"]
"required": [
"text",
"type",
"path"
]
},
"Range": {
"type": "object",
@@ -7828,7 +8192,10 @@
"type": "number"
}
},
"required": ["line", "character"]
"required": [
"line",
"character"
]
},
"end": {
"type": "object",
@@ -7840,10 +8207,16 @@
"type": "number"
}
},
"required": ["line", "character"]
"required": [
"line",
"character"
]
}
},
"required": ["start", "end"]
"required": [
"start",
"end"
]
},
"SymbolSource": {
"type": "object",
@@ -7870,7 +8243,14 @@
"maximum": 9007199254740991
}
},
"required": ["text", "type", "path", "range", "name", "kind"]
"required": [
"text",
"type",
"path",
"range",
"name",
"kind"
]
},
"ResourceSource": {
"type": "object",
@@ -7889,7 +8269,12 @@
"type": "string"
}
},
"required": ["text", "type", "clientName", "uri"]
"required": [
"text",
"type",
"clientName",
"uri"
]
},
"FilePartSource": {
"anyOf": [
@@ -7936,7 +8321,14 @@
"$ref": "#/components/schemas/FilePartSource"
}
},
"required": ["id", "sessionID", "messageID", "type", "mime", "url"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"mime",
"url"
]
},
"ToolStatePending": {
"type": "object",
@@ -7956,7 +8348,11 @@
"type": "string"
}
},
"required": ["status", "input", "raw"]
"required": [
"status",
"input",
"raw"
]
},
"ToolStateRunning": {
"type": "object",
@@ -7989,10 +8385,16 @@
"type": "number"
}
},
"required": ["start"]
"required": [
"start"
]
}
},
"required": ["status", "input", "time"]
"required": [
"status",
"input",
"time"
]
},
"ToolStateCompleted": {
"type": "object",
@@ -8034,7 +8436,10 @@
"type": "number"
}
},
"required": ["start", "end"]
"required": [
"start",
"end"
]
},
"attachments": {
"type": "array",
@@ -8043,7 +8448,14 @@
}
}
},
"required": ["status", "input", "output", "title", "metadata", "time"]
"required": [
"status",
"input",
"output",
"title",
"metadata",
"time"
]
},
"ToolStateError": {
"type": "object",
@@ -8079,10 +8491,18 @@
"type": "number"
}
},
"required": ["start", "end"]
"required": [
"start",
"end"
]
}
},
"required": ["status", "input", "error", "time"]
"required": [
"status",
"input",
"error",
"time"
]
},
"ToolState": {
"anyOf": [
@@ -8136,7 +8556,15 @@
"additionalProperties": {}
}
},
"required": ["id", "sessionID", "messageID", "type", "callID", "tool", "state"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"callID",
"tool",
"state"
]
},
"StepStartPart": {
"type": "object",
@@ -8161,7 +8589,12 @@
"type": "string"
}
},
"required": ["id", "sessionID", "messageID", "type"]
"required": [
"id",
"sessionID",
"messageID",
"type"
]
},
"StepFinishPart": {
"type": "object",
@@ -8216,13 +8649,29 @@
"type": "number"
}
},
"required": ["read", "write"]
"required": [
"read",
"write"
]
}
},
"required": ["input", "output", "reasoning", "cache"]
"required": [
"input",
"output",
"reasoning",
"cache"
]
}
},
"required": ["id", "sessionID", "messageID", "type", "reason", "cost", "tokens"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"reason",
"cost",
"tokens"
]
},
"SnapshotPart": {
"type": "object",
@@ -8247,7 +8696,13 @@
"type": "string"
}
},
"required": ["id", "sessionID", "messageID", "type", "snapshot"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"snapshot"
]
},
"PatchPart": {
"type": "object",
@@ -8278,7 +8733,14 @@
}
}
},
"required": ["id", "sessionID", "messageID", "type", "hash", "files"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"hash",
"files"
]
},
"AgentPart": {
"type": "object",
@@ -8319,10 +8781,20 @@
"maximum": 9007199254740991
}
},
"required": ["value", "start", "end"]
"required": [
"value",
"start",
"end"
]
}
},
"required": ["id", "sessionID", "messageID", "type", "name"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"name"
]
},
"RetryPart": {
"type": "object",
@@ -8356,10 +8828,20 @@
"type": "number"
}
},
"required": ["created"]
"required": [
"created"
]
}
},
"required": ["id", "sessionID", "messageID", "type", "attempt", "error", "time"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"attempt",
"error",
"time"
]
},
"CompactionPart": {
"type": "object",
@@ -8387,7 +8869,13 @@
"type": "boolean"
}
},
"required": ["id", "sessionID", "messageID", "type", "auto"]
"required": [
"id",
"sessionID",
"messageID",
"type",
"auto"
]
},
"Part": {
"anyOf": [
@@ -8443,10 +8931,15 @@
"$ref": "#/components/schemas/Part"
}
},
"required": ["part"]
"required": [
"part"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.message.part.delta": {
"type": "object",
@@ -8477,10 +8970,19 @@
"type": "string"
}
},
"required": ["sessionID", "messageID", "partID", "field", "delta"]
"required": [
"sessionID",
"messageID",
"partID",
"field",
"delta"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.message.part.removed": {
"type": "object",
@@ -8505,10 +9007,17 @@
"pattern": "^prt.*"
}
},
"required": ["sessionID", "messageID", "partID"]
"required": [
"sessionID",
"messageID",
"partID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"PermissionRequest": {
"type": "object",
@@ -8554,10 +9063,20 @@
"type": "string"
}
},
"required": ["messageID", "callID"]
"required": [
"messageID",
"callID"
]
}
},
"required": ["id", "sessionID", "permission", "patterns", "metadata", "always"]
"required": [
"id",
"sessionID",
"permission",
"patterns",
"metadata",
"always"
]
},
"Event.permission.asked": {
"type": "object",
@@ -8570,7 +9089,10 @@
"$ref": "#/components/schemas/PermissionRequest"
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.permission.replied": {
"type": "object",
@@ -8592,13 +9114,24 @@
},
"reply": {
"type": "string",
"enum": ["once", "always", "reject"]
"enum": [
"once",
"always",
"reject"
]
}
},
"required": ["sessionID", "requestID", "reply"]
"required": [
"sessionID",
"requestID",
"reply"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"SessionStatus": {
"anyOf": [
@@ -8610,7 +9143,9 @@
"const": "idle"
}
},
"required": ["type"]
"required": [
"type"
]
},
{
"type": "object",
@@ -8629,7 +9164,12 @@
"type": "number"
}
},
"required": ["type", "attempt", "message", "next"]
"required": [
"type",
"attempt",
"message",
"next"
]
},
{
"type": "object",
@@ -8639,7 +9179,9 @@
"const": "busy"
}
},
"required": ["type"]
"required": [
"type"
]
}
]
},
@@ -8661,10 +9203,16 @@
"$ref": "#/components/schemas/SessionStatus"
}
},
"required": ["sessionID", "status"]
"required": [
"sessionID",
"status"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.idle": {
"type": "object",
@@ -8681,10 +9229,15 @@
"pattern": "^ses.*"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"QuestionOption": {
"type": "object",
@@ -8698,7 +9251,10 @@
"type": "string"
}
},
"required": ["label", "description"]
"required": [
"label",
"description"
]
},
"QuestionInfo": {
"type": "object",
@@ -8727,7 +9283,11 @@
"type": "boolean"
}
},
"required": ["question", "header", "options"]
"required": [
"question",
"header",
"options"
]
},
"QuestionRequest": {
"type": "object",
@@ -8758,10 +9318,17 @@
"type": "string"
}
},
"required": ["messageID", "callID"]
"required": [
"messageID",
"callID"
]
}
},
"required": ["id", "sessionID", "questions"]
"required": [
"id",
"sessionID",
"questions"
]
},
"Event.question.asked": {
"type": "object",
@@ -8774,7 +9341,10 @@
"$ref": "#/components/schemas/QuestionRequest"
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"QuestionAnswer": {
"type": "array",
@@ -8807,10 +9377,17 @@
}
}
},
"required": ["sessionID", "requestID", "answers"]
"required": [
"sessionID",
"requestID",
"answers"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.question.rejected": {
"type": "object",
@@ -8831,10 +9408,16 @@
"pattern": "^que.*"
}
},
"required": ["sessionID", "requestID"]
"required": [
"sessionID",
"requestID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.compacted": {
"type": "object",
@@ -8851,10 +9434,15 @@
"pattern": "^ses.*"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.file.watcher.updated": {
"type": "object",
@@ -8886,10 +9474,16 @@
]
}
},
"required": ["file", "event"]
"required": [
"file",
"event"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Todo": {
"type": "object",
@@ -8907,7 +9501,11 @@
"type": "string"
}
},
"required": ["content", "status", "priority"]
"required": [
"content",
"status",
"priority"
]
},
"Event.todo.updated": {
"type": "object",
@@ -8930,10 +9528,16 @@
}
}
},
"required": ["sessionID", "todos"]
"required": [
"sessionID",
"todos"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.tui.prompt.append": {
"type": "object",
@@ -8949,10 +9553,15 @@
"type": "string"
}
},
"required": ["text"]
"required": [
"text"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.tui.command.execute": {
"type": "object",
@@ -8993,10 +9602,15 @@
]
}
},
"required": ["command"]
"required": [
"command"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.tui.toast.show": {
"type": "object",
@@ -9016,7 +9630,12 @@
},
"variant": {
"type": "string",
"enum": ["info", "success", "warning", "error"]
"enum": [
"info",
"success",
"warning",
"error"
]
},
"duration": {
"description": "Duration in milliseconds",
@@ -9024,10 +9643,16 @@
"type": "number"
}
},
"required": ["message", "variant"]
"required": [
"message",
"variant"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.tui.session.select": {
"type": "object",
@@ -9045,10 +9670,15 @@
"pattern": "^ses.*"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.mcp.tools.changed": {
"type": "object",
@@ -9064,10 +9694,15 @@
"type": "string"
}
},
"required": ["server"]
"required": [
"server"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.mcp.browser.open.failed": {
"type": "object",
@@ -9086,10 +9721,16 @@
"type": "string"
}
},
"required": ["mcpName", "url"]
"required": [
"mcpName",
"url"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.command.executed": {
"type": "object",
@@ -9116,14 +9757,26 @@
"pattern": "^msg.*"
}
},
"required": ["name", "sessionID", "arguments", "messageID"]
"required": [
"name",
"sessionID",
"arguments",
"messageID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"PermissionAction": {
"type": "string",
"enum": ["allow", "deny", "ask"]
"enum": [
"allow",
"deny",
"ask"
]
},
"PermissionRule": {
"type": "object",
@@ -9138,7 +9791,11 @@
"$ref": "#/components/schemas/PermissionAction"
}
},
"required": ["permission", "pattern", "action"]
"required": [
"permission",
"pattern",
"action"
]
},
"PermissionRuleset": {
"type": "array",
@@ -9189,7 +9846,11 @@
}
}
},
"required": ["additions", "deletions", "files"]
"required": [
"additions",
"deletions",
"files"
]
},
"share": {
"type": "object",
@@ -9198,7 +9859,9 @@
"type": "string"
}
},
"required": ["url"]
"required": [
"url"
]
},
"title": {
"type": "string"
@@ -9222,7 +9885,10 @@
"type": "number"
}
},
"required": ["created", "updated"]
"required": [
"created",
"updated"
]
},
"permission": {
"$ref": "#/components/schemas/PermissionRuleset"
@@ -9245,10 +9911,20 @@
"type": "string"
}
},
"required": ["messageID"]
"required": [
"messageID"
]
}
},
"required": ["id", "slug", "projectID", "directory", "title", "version", "time"]
"required": [
"id",
"slug",
"projectID",
"directory",
"title",
"version",
"time"
]
},
"Event.session.created": {
"type": "object",
@@ -9264,10 +9940,15 @@
"$ref": "#/components/schemas/Session"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.updated": {
"type": "object",
@@ -9283,10 +9964,15 @@
"$ref": "#/components/schemas/Session"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.deleted": {
"type": "object",
@@ -9302,10 +9988,15 @@
"$ref": "#/components/schemas/Session"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.diff": {
"type": "object",
@@ -9328,10 +10019,16 @@
}
}
},
"required": ["sessionID", "diff"]
"required": [
"sessionID",
"diff"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.error": {
"type": "object",
@@ -9375,7 +10072,10 @@
}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.vcs.branch.updated": {
"type": "object",
@@ -9393,7 +10093,10 @@
}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.workspace.ready": {
"type": "object",
@@ -9409,10 +10112,15 @@
"type": "string"
}
},
"required": ["name"]
"required": [
"name"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.workspace.failed": {
"type": "object",
@@ -9428,10 +10136,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Pty": {
"type": "object",
@@ -9457,13 +10170,24 @@
},
"status": {
"type": "string",
"enum": ["running", "exited"]
"enum": [
"running",
"exited"
]
},
"pid": {
"type": "number"
}
},
"required": ["id", "title", "command", "args", "cwd", "status", "pid"]
"required": [
"id",
"title",
"command",
"args",
"cwd",
"status",
"pid"
]
},
"Event.pty.created": {
"type": "object",
@@ -9479,10 +10203,15 @@
"$ref": "#/components/schemas/Pty"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.pty.updated": {
"type": "object",
@@ -9498,10 +10227,15 @@
"$ref": "#/components/schemas/Pty"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.pty.exited": {
"type": "object",
@@ -9521,10 +10255,16 @@
"type": "number"
}
},
"required": ["id", "exitCode"]
"required": [
"id",
"exitCode"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.pty.deleted": {
"type": "object",
@@ -9541,10 +10281,15 @@
"pattern": "^pty.*"
}
},
"required": ["id"]
"required": [
"id"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.worktree.ready": {
"type": "object",
@@ -9563,10 +10308,16 @@
"type": "string"
}
},
"required": ["name", "branch"]
"required": [
"name",
"branch"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.worktree.failed": {
"type": "object",
@@ -9582,10 +10333,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event": {
"anyOf": [
@@ -9736,12 +10492,20 @@
"$ref": "#/components/schemas/Event"
}
},
"required": ["directory", "payload"]
"required": [
"directory",
"payload"
]
},
"LogLevel": {
"description": "Log level",
"type": "string",
"enum": ["DEBUG", "INFO", "WARN", "ERROR"]
"enum": [
"DEBUG",
"INFO",
"WARN",
"ERROR"
]
},
"ServerConfig": {
"description": "Server configuration for opencode serve and web commands",
@@ -9777,7 +10541,11 @@
},
"PermissionActionConfig": {
"type": "string",
"enum": ["ask", "allow", "deny"]
"enum": [
"ask",
"allow",
"deny"
]
},
"PermissionObjectConfig": {
"type": "object",
@@ -9908,7 +10676,11 @@
},
"mode": {
"type": "string",
"enum": ["subagent", "primary", "all"]
"enum": [
"subagent",
"primary",
"all"
]
},
"hidden": {
"description": "Hide this subagent from the @ autocomplete menu (default: false, only applies to mode: subagent)",
@@ -9930,7 +10702,15 @@
},
{
"type": "string",
"enum": ["primary", "secondary", "accent", "success", "warning", "error", "info"]
"enum": [
"primary",
"secondary",
"accent",
"success",
"warning",
"error",
"info"
]
}
]
},
@@ -10016,10 +10796,15 @@
"properties": {
"field": {
"type": "string",
"enum": ["reasoning_content", "reasoning_details"]
"enum": [
"reasoning_content",
"reasoning_details"
]
}
},
"required": ["field"],
"required": [
"field"
],
"additionalProperties": false
}
]
@@ -10055,10 +10840,16 @@
"type": "number"
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"limit": {
"type": "object",
@@ -10073,7 +10864,10 @@
"type": "number"
}
},
"required": ["context", "output"]
"required": [
"context",
"output"
]
},
"modalities": {
"type": "object",
@@ -10082,25 +10876,44 @@
"type": "array",
"items": {
"type": "string",
"enum": ["text", "audio", "image", "video", "pdf"]
"enum": [
"text",
"audio",
"image",
"video",
"pdf"
]
}
},
"output": {
"type": "array",
"items": {
"type": "string",
"enum": ["text", "audio", "image", "video", "pdf"]
"enum": [
"text",
"audio",
"image",
"video",
"pdf"
]
}
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"experimental": {
"type": "boolean"
},
"status": {
"type": "string",
"enum": ["alpha", "beta", "deprecated"]
"enum": [
"alpha",
"beta",
"deprecated"
]
},
"options": {
"type": "object",
@@ -10242,7 +11055,10 @@
"maximum": 9007199254740991
}
},
"required": ["type", "command"],
"required": [
"type",
"command"
],
"additionalProperties": false
},
"McpOAuthConfig": {
@@ -10308,13 +11124,19 @@
"maximum": 9007199254740991
}
},
"required": ["type", "url"],
"required": [
"type",
"url"
],
"additionalProperties": false
},
"LayoutConfig": {
"description": "@deprecated Always uses stretch layout.",
"type": "string",
"enum": ["auto", "stretch"]
"enum": [
"auto",
"stretch"
]
},
"Config": {
"type": "object",
@@ -10354,7 +11176,9 @@
"type": "boolean"
}
},
"required": ["template"]
"required": [
"template"
]
}
},
"skills": {
@@ -10400,7 +11224,11 @@
"share": {
"description": "Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing",
"type": "string",
"enum": ["manual", "auto", "disabled"]
"enum": [
"manual",
"auto",
"disabled"
]
},
"autoshare": {
"description": "@deprecated Use 'share' field instead. Share newly created sessions automatically",
@@ -10528,7 +11356,9 @@
"type": "boolean"
}
},
"required": ["enabled"],
"required": [
"enabled"
],
"additionalProperties": false
}
]
@@ -10598,7 +11428,9 @@
"const": true
}
},
"required": ["disabled"]
"required": [
"disabled"
]
},
{
"type": "object",
@@ -10635,7 +11467,9 @@
"additionalProperties": {}
}
},
"required": ["command"]
"required": [
"command"
]
}
]
}
@@ -10747,7 +11581,11 @@
"const": false
}
},
"required": ["data", "errors", "success"]
"required": [
"data",
"errors",
"success"
]
},
"OAuth": {
"type": "object",
@@ -10772,7 +11610,12 @@
"type": "string"
}
},
"required": ["type", "refresh", "access", "expires"]
"required": [
"type",
"refresh",
"access",
"expires"
]
},
"ApiAuth": {
"type": "object",
@@ -10785,7 +11628,10 @@
"type": "string"
}
},
"required": ["type", "key"]
"required": [
"type",
"key"
]
},
"WellKnownAuth": {
"type": "object",
@@ -10801,7 +11647,11 @@
"type": "string"
}
},
"required": ["type", "key", "token"]
"required": [
"type",
"key",
"token"
]
},
"Auth": {
"anyOf": [
@@ -10830,10 +11680,15 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"Model": {
"type": "object",
@@ -10857,7 +11712,11 @@
"type": "string"
}
},
"required": ["id", "url", "npm"]
"required": [
"id",
"url",
"npm"
]
},
"name": {
"type": "string"
@@ -10899,7 +11758,13 @@
"type": "boolean"
}
},
"required": ["text", "audio", "image", "video", "pdf"]
"required": [
"text",
"audio",
"image",
"video",
"pdf"
]
},
"output": {
"type": "object",
@@ -10920,7 +11785,13 @@
"type": "boolean"
}
},
"required": ["text", "audio", "image", "video", "pdf"]
"required": [
"text",
"audio",
"image",
"video",
"pdf"
]
},
"interleaved": {
"anyOf": [
@@ -10932,15 +11803,28 @@
"properties": {
"field": {
"type": "string",
"enum": ["reasoning_content", "reasoning_details"]
"enum": [
"reasoning_content",
"reasoning_details"
]
}
},
"required": ["field"]
"required": [
"field"
]
}
]
}
},
"required": ["temperature", "reasoning", "attachment", "toolcall", "input", "output", "interleaved"]
"required": [
"temperature",
"reasoning",
"attachment",
"toolcall",
"input",
"output",
"interleaved"
]
},
"cost": {
"type": "object",
@@ -10961,7 +11845,10 @@
"type": "number"
}
},
"required": ["read", "write"]
"required": [
"read",
"write"
]
},
"experimentalOver200K": {
"type": "object",
@@ -10982,13 +11869,24 @@
"type": "number"
}
},
"required": ["read", "write"]
"required": [
"read",
"write"
]
}
},
"required": ["input", "output", "cache"]
"required": [
"input",
"output",
"cache"
]
}
},
"required": ["input", "output", "cache"]
"required": [
"input",
"output",
"cache"
]
},
"limit": {
"type": "object",
@@ -11003,11 +11901,19 @@
"type": "number"
}
},
"required": ["context", "output"]
"required": [
"context",
"output"
]
},
"status": {
"type": "string",
"enum": ["alpha", "beta", "deprecated", "active"]
"enum": [
"alpha",
"beta",
"deprecated",
"active"
]
},
"options": {
"type": "object",
@@ -11067,7 +11973,12 @@
},
"source": {
"type": "string",
"enum": ["env", "config", "custom", "api"]
"enum": [
"env",
"config",
"custom",
"api"
]
},
"env": {
"type": "array",
@@ -11095,7 +12006,14 @@
}
}
},
"required": ["id", "name", "source", "env", "options", "models"]
"required": [
"id",
"name",
"source",
"env",
"options",
"models"
]
},
"ToolIDs": {
"type": "array",
@@ -11114,7 +12032,11 @@
},
"parameters": {}
},
"required": ["id", "description", "parameters"]
"required": [
"id",
"description",
"parameters"
]
},
"ToolList": {
"type": "array",
@@ -11174,7 +12096,15 @@
"type": "string"
}
},
"required": ["id", "type", "branch", "name", "directory", "extra", "projectID"]
"required": [
"id",
"type",
"branch",
"name",
"directory",
"extra",
"projectID"
]
},
"Worktree": {
"type": "object",
@@ -11189,7 +12119,11 @@
"type": "string"
}
},
"required": ["name", "branch", "directory"]
"required": [
"name",
"branch",
"directory"
]
},
"WorktreeCreateInput": {
"type": "object",
@@ -11210,7 +12144,9 @@
"type": "string"
}
},
"required": ["directory"]
"required": [
"directory"
]
},
"WorktreeResetInput": {
"type": "object",
@@ -11219,7 +12155,9 @@
"type": "string"
}
},
"required": ["directory"]
"required": [
"directory"
]
},
"ProjectSummary": {
"type": "object",
@@ -11234,7 +12172,10 @@
"type": "string"
}
},
"required": ["id", "worktree"]
"required": [
"id",
"worktree"
]
},
"GlobalSession": {
"type": "object",
@@ -11279,7 +12220,11 @@
}
}
},
"required": ["additions", "deletions", "files"]
"required": [
"additions",
"deletions",
"files"
]
},
"share": {
"type": "object",
@@ -11288,7 +12233,9 @@
"type": "string"
}
},
"required": ["url"]
"required": [
"url"
]
},
"title": {
"type": "string"
@@ -11312,7 +12259,10 @@
"type": "number"
}
},
"required": ["created", "updated"]
"required": [
"created",
"updated"
]
},
"permission": {
"$ref": "#/components/schemas/PermissionRuleset"
@@ -11335,7 +12285,9 @@
"type": "string"
}
},
"required": ["messageID"]
"required": [
"messageID"
]
},
"project": {
"anyOf": [
@@ -11348,7 +12300,16 @@
]
}
},
"required": ["id", "slug", "projectID", "directory", "title", "version", "time", "project"]
"required": [
"id",
"slug",
"projectID",
"directory",
"title",
"version",
"time",
"project"
]
},
"McpResource": {
"type": "object",
@@ -11369,7 +12330,11 @@
"type": "string"
}
},
"required": ["name", "uri", "client"]
"required": [
"name",
"uri",
"client"
]
},
"TextPartInput": {
"type": "object",
@@ -11401,7 +12366,9 @@
"type": "number"
}
},
"required": ["start"]
"required": [
"start"
]
},
"metadata": {
"type": "object",
@@ -11411,7 +12378,10 @@
"additionalProperties": {}
}
},
"required": ["type", "text"]
"required": [
"type",
"text"
]
},
"FilePartInput": {
"type": "object",
@@ -11437,7 +12407,11 @@
"$ref": "#/components/schemas/FilePartSource"
}
},
"required": ["type", "mime", "url"]
"required": [
"type",
"mime",
"url"
]
},
"AgentPartInput": {
"type": "object",
@@ -11470,10 +12444,17 @@
"maximum": 9007199254740991
}
},
"required": ["value", "start", "end"]
"required": [
"value",
"start",
"end"
]
}
},
"required": ["type", "name"]
"required": [
"type",
"name"
]
},
"SubtaskPartInput": {
"type": "object",
@@ -11505,13 +12486,21 @@
"type": "string"
}
},
"required": ["providerID", "modelID"]
"required": [
"providerID",
"modelID"
]
},
"command": {
"type": "string"
}
},
"required": ["type", "prompt", "description", "agent"]
"required": [
"type",
"prompt",
"description",
"agent"
]
},
"ProviderAuthMethod": {
"type": "object",
@@ -11532,7 +12521,10 @@
"type": "string"
}
},
"required": ["type", "label"]
"required": [
"type",
"label"
]
},
"ProviderAuthAuthorization": {
"type": "object",
@@ -11556,7 +12548,11 @@
"type": "string"
}
},
"required": ["url", "method", "instructions"]
"required": [
"url",
"method",
"instructions"
]
},
"Symbol": {
"type": "object",
@@ -11577,10 +12573,17 @@
"$ref": "#/components/schemas/Range"
}
},
"required": ["uri", "range"]
"required": [
"uri",
"range"
]
}
},
"required": ["name", "kind", "location"]
"required": [
"name",
"kind",
"location"
]
},
"FileNode": {
"type": "object",
@@ -11596,20 +12599,32 @@
},
"type": {
"type": "string",
"enum": ["file", "directory"]
"enum": [
"file",
"directory"
]
},
"ignored": {
"type": "boolean"
}
},
"required": ["name", "path", "absolute", "type", "ignored"]
"required": [
"name",
"path",
"absolute",
"type",
"ignored"
]
},
"FileContent": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["text", "binary"]
"enum": [
"text",
"binary"
]
},
"content": {
"type": "string"
@@ -11656,14 +12671,24 @@
}
}
},
"required": ["oldStart", "oldLines", "newStart", "newLines", "lines"]
"required": [
"oldStart",
"oldLines",
"newStart",
"newLines",
"lines"
]
}
},
"index": {
"type": "string"
}
},
"required": ["oldFileName", "newFileName", "hunks"]
"required": [
"oldFileName",
"newFileName",
"hunks"
]
},
"encoding": {
"type": "string",
@@ -11673,7 +12698,10 @@
"type": "string"
}
},
"required": ["type", "content"]
"required": [
"type",
"content"
]
},
"File": {
"type": "object",
@@ -11693,10 +12721,19 @@
},
"status": {
"type": "string",
"enum": ["added", "deleted", "modified"]
"enum": [
"added",
"deleted",
"modified"
]
}
},
"required": ["path", "added", "removed", "status"]
"required": [
"path",
"added",
"removed",
"status"
]
},
"MCPStatusConnected": {
"type": "object",
@@ -11706,7 +12743,9 @@
"const": "connected"
}
},
"required": ["status"]
"required": [
"status"
]
},
"MCPStatusDisabled": {
"type": "object",
@@ -11716,7 +12755,9 @@
"const": "disabled"
}
},
"required": ["status"]
"required": [
"status"
]
},
"MCPStatusFailed": {
"type": "object",
@@ -11729,7 +12770,10 @@
"type": "string"
}
},
"required": ["status", "error"]
"required": [
"status",
"error"
]
},
"MCPStatusNeedsAuth": {
"type": "object",
@@ -11739,7 +12783,9 @@
"const": "needs_auth"
}
},
"required": ["status"]
"required": [
"status"
]
},
"MCPStatusNeedsClientRegistration": {
"type": "object",
@@ -11752,7 +12798,10 @@
"type": "string"
}
},
"required": ["status", "error"]
"required": [
"status",
"error"
]
},
"MCPStatus": {
"anyOf": [
@@ -11792,7 +12841,13 @@
"type": "string"
}
},
"required": ["home", "state", "config", "worktree", "directory"]
"required": [
"home",
"state",
"config",
"worktree",
"directory"
]
},
"VcsInfo": {
"type": "object",
@@ -11801,7 +12856,9 @@
"type": "string"
}
},
"required": ["branch"]
"required": [
"branch"
]
},
"Command": {
"type": "object",
@@ -11820,7 +12877,11 @@
},
"source": {
"type": "string",
"enum": ["command", "mcp", "skill"]
"enum": [
"command",
"mcp",
"skill"
]
},
"template": {
"anyOf": [
@@ -11842,7 +12903,11 @@
}
}
},
"required": ["name", "template", "hints"]
"required": [
"name",
"template",
"hints"
]
},
"Agent": {
"type": "object",
@@ -11855,7 +12920,11 @@
},
"mode": {
"type": "string",
"enum": ["subagent", "primary", "all"]
"enum": [
"subagent",
"primary",
"all"
]
},
"native": {
"type": "boolean"
@@ -11885,7 +12954,10 @@
"type": "string"
}
},
"required": ["modelID", "providerID"]
"required": [
"modelID",
"providerID"
]
},
"variant": {
"type": "string"
@@ -11906,7 +12978,12 @@
"maximum": 9007199254740991
}
},
"required": ["name", "mode", "permission", "options"]
"required": [
"name",
"mode",
"permission",
"options"
]
},
"LSPStatus": {
"type": "object",
@@ -11933,7 +13010,12 @@
]
}
},
"required": ["id", "name", "root", "status"]
"required": [
"id",
"name",
"root",
"status"
]
},
"FormatterStatus": {
"type": "object",
@@ -11951,8 +13033,12 @@
"type": "boolean"
}
},
"required": ["name", "extensions", "enabled"]
"required": [
"name",
"extensions",
"enabled"
]
}
}
}
}
}