Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""add curr_run_id to agent_session_history

Revision ID: 243a597b6a3a
Revises: e1a2b3c4d5f6
Create Date: 2026-05-27 10:43:33.204849

"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "243a597b6a3a"
down_revision: str | None = "e1a2b3c4d5f6"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
op.add_column(
"agent_session_history",
sa.Column("curr_run_id", sa.UUID(), nullable=True),
)
op.create_index(
op.f("ix_agent_session_history_curr_run_id"),
"agent_session_history",
["curr_run_id"],
unique=False,
)


def downgrade() -> None:
op.drop_index(
op.f("ix_agent_session_history_curr_run_id"),
table_name="agent_session_history",
)
op.drop_column("agent_session_history", "curr_run_id")
40 changes: 40 additions & 0 deletions frontend/src/client/schemas.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4037,6 +4037,46 @@ export const $AgentSessionStatus = {
description: "Lifecycle state for an agent session turn.",
} as const

export const $AgentSessionStatusRead = {
properties: {
turn_status: {
$ref: "#/components/schemas/AgentSessionStatus",
default: "idle",
},
curr_run_id: {
anyOf: [
{
type: "string",
format: "uuid",
},
{
type: "null",
},
],
title: "Curr Run Id",
},
prompt: {
anyOf: [
{
type: "string",
},
{
type: "null",
},
],
title: "Prompt",
description:
"Human prompt that started the active run, for observer clients to render (user messages cannot stream over the Vercel protocol).",
},
},
type: "object",
title: "AgentSessionStatusRead",
description: `Lightweight session lifecycle status for cheap polling.

Clients poll this (instead of the full message history) to learn when a turn
starts elsewhere and attach to the live stream.`,
} as const

export const $AgentSessionUpdate = {
properties: {
title: {
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/client/services.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ import type {
AgentSessionsForkSessionResponse,
AgentSessionsGetSessionData,
AgentSessionsGetSessionResponse,
AgentSessionsGetSessionStatusData,
AgentSessionsGetSessionStatusResponse,
AgentSessionsGetSessionVercelData,
AgentSessionsGetSessionVercelResponse,
AgentSessionsListSessionsData,
Expand Down Expand Up @@ -6613,6 +6615,31 @@ export const agentSessionsGetSessionVercel = (
})
}

/**
* Get Session Status
* Lifecycle status for polling without loading message history.
* @param data The data for the request.
* @param data.sessionId
* @param data.workspaceId
* @returns AgentSessionStatusRead Successful Response
* @throws ApiError
*/
export const agentSessionsGetSessionStatus = (
data: AgentSessionsGetSessionStatusData
): CancelablePromise<AgentSessionsGetSessionStatusResponse> => {
return __request(OpenAPI, {
method: "GET",
url: "/workspaces/{workspace_id}/agent/sessions/{session_id}/status",
path: {
session_id: data.sessionId,
workspace_id: data.workspaceId,
},
errors: {
422: "Validation Error",
},
})
}

/**
* Cancel Session
* Request graceful cancellation for the active agent session turn.
Expand Down
37 changes: 37 additions & 0 deletions frontend/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,21 @@ export type AgentSessionStatus =
| "stopped"
| "failed"

/**
* Lightweight session lifecycle status for cheap polling.
*
* Clients poll this (instead of the full message history) to learn when a turn
* starts elsewhere and attach to the live stream.
*/
export type AgentSessionStatusRead = {
turn_status?: AgentSessionStatus
curr_run_id?: string | null
/**
* Human prompt that started the active run, for observer clients to render (user messages cannot stream over the Vercel protocol).
*/
prompt?: string | null
}

/**
* Request schema for updating an agent session.
*/
Expand Down Expand Up @@ -10781,6 +10796,13 @@ export type AgentSessionsGetSessionVercelResponse =
| AgentSessionReadVercel
| ChatReadVercel

export type AgentSessionsGetSessionStatusData = {
sessionId: string
workspaceId: string
}

export type AgentSessionsGetSessionStatusResponse = AgentSessionStatusRead

export type AgentSessionsCancelSessionData = {
requestBody?: AgentSessionCancelRequest | null
sessionId: string
Expand Down Expand Up @@ -15780,6 +15802,21 @@ export type $OpenApiTs = {
}
}
}
"/workspaces/{workspace_id}/agent/sessions/{session_id}/status": {
get: {
req: AgentSessionsGetSessionStatusData
res: {
/**
* Successful Response
*/
200: AgentSessionStatusRead
/**
* Validation Error
*/
422: HTTPValidationError
}
}
}
"/workspaces/{workspace_id}/agent/sessions/{session_id}/cancel": {
post: {
req: AgentSessionsCancelSessionData
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/components/chat/chat-session-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ import {
makeContinueMessage,
parseChatError,
useCancelChatTurn,
useSessionStatus,
useUpdateChat,
useVercelChat,
} from "@/hooks/use-chat"
Expand Down Expand Up @@ -279,12 +280,26 @@ export function ChatSessionPane({
() => (chat?.messages || []).map(toUIMessage),
[chat?.messages]
)
// Cheap status poll drives attaching to a live turn (started by another tab).
// `prompt` carries the active turn's user message so observer tabs can show
// it (the Vercel stream protocol only streams assistant messages).
const {
turnStatus,
currRunId,
prompt: activePrompt,
} = useSessionStatus({
chatId: isReadonly ? undefined : chat?.id,
workspaceId,
Comment thread
jordan-umusu marked this conversation as resolved.
})
const { sendMessage, messages, status, regenerate, lastError, clearError } =
useVercelChat({
chatId: chat?.id,
workspaceId,
messages: uiMessages,
modelInfo,
turnStatus,
currRunId,
activePrompt,
})

// Track pending message sends to avoid duplicate sends
Expand Down
Loading
Loading