fix(webapp): keep the close action available for idle sessions
Address review on the sessions status change: - Keep the "Close session" action on the detail page for Idle sessions; they are open, only Closed and Expired are terminal. - Rename the status helper input from currentRunId to hasCurrentRun, since the detail page passes a run friendlyId, not the session's currentRunId. - Restore the Active tooltip copy so it stays accurate now that the Active filter also returns open, idle sessions. - Align the sessions docs example so the listed tag matches a top-level tag set at start time.
This commit is contained in:
@@ -13,7 +13,7 @@ export const allSessionStatuses = ["ACTIVE", "CLOSED", "EXPIRED"] as const satis
|
||||
>;
|
||||
|
||||
const descriptions: Record<SessionDisplayStatus, string> = {
|
||||
ACTIVE: "The session has a run currently executing.",
|
||||
ACTIVE: "The session is open and can receive input or schedule new runs.",
|
||||
IDLE: "The session is open but has no run currently executing.",
|
||||
CLOSED: "The session was closed; no further input or runs can be triggered against it.",
|
||||
EXPIRED: "The session passed its expiry time without being closed explicitly.",
|
||||
|
||||
@@ -214,7 +214,7 @@ export class SessionListPresenter {
|
||||
const status = deriveSessionStatus({
|
||||
closedAt: session.closedAt,
|
||||
expiresAt: session.expiresAt,
|
||||
currentRunId: session.currentRunId,
|
||||
hasCurrentRun: session.currentRunId != null,
|
||||
currentRunStatus: currentRun?.status,
|
||||
now,
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: PAST,
|
||||
expiresAt: null,
|
||||
currentRunId: "run_1",
|
||||
hasCurrentRun: true,
|
||||
currentRunStatus: "EXECUTING",
|
||||
now: NOW,
|
||||
})
|
||||
@@ -23,7 +23,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: PAST,
|
||||
expiresAt: PAST,
|
||||
currentRunId: null,
|
||||
hasCurrentRun: false,
|
||||
currentRunStatus: undefined,
|
||||
now: NOW,
|
||||
})
|
||||
@@ -35,7 +35,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: null,
|
||||
expiresAt: PAST,
|
||||
currentRunId: "run_1",
|
||||
hasCurrentRun: true,
|
||||
currentRunStatus: "EXECUTING",
|
||||
now: NOW,
|
||||
})
|
||||
@@ -47,7 +47,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: null,
|
||||
expiresAt: FUTURE,
|
||||
currentRunId: "run_1",
|
||||
hasCurrentRun: true,
|
||||
currentRunStatus: "EXECUTING",
|
||||
now: NOW,
|
||||
})
|
||||
@@ -59,7 +59,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: null,
|
||||
expiresAt: null,
|
||||
currentRunId: "run_1",
|
||||
hasCurrentRun: true,
|
||||
currentRunStatus: "EXPIRED",
|
||||
now: NOW,
|
||||
})
|
||||
@@ -71,7 +71,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: null,
|
||||
expiresAt: null,
|
||||
currentRunId: null,
|
||||
hasCurrentRun: false,
|
||||
currentRunStatus: undefined,
|
||||
now: NOW,
|
||||
})
|
||||
@@ -83,7 +83,7 @@ describe("deriveSessionStatus", () => {
|
||||
deriveSessionStatus({
|
||||
closedAt: null,
|
||||
expiresAt: null,
|
||||
currentRunId: "run_missing",
|
||||
hasCurrentRun: true,
|
||||
currentRunStatus: undefined,
|
||||
now: NOW,
|
||||
})
|
||||
|
||||
@@ -7,11 +7,11 @@ export type DeriveSessionStatusInput = {
|
||||
closedAt: Date | null;
|
||||
/** `Session.expiresAt` — retention deadline, if any. */
|
||||
expiresAt: Date | null;
|
||||
/** `Session.currentRunId` — pointer to the current run (no FK). */
|
||||
currentRunId: string | null;
|
||||
/** Whether the session points at a current run at all. */
|
||||
hasCurrentRun: boolean;
|
||||
/**
|
||||
* Status of the run named by `currentRunId`. `undefined` when there is no
|
||||
* current run, or the pointer couldn't be resolved (stale / cross-env).
|
||||
* Status of the current run. `undefined` when there is no current run, or the
|
||||
* pointer couldn't be resolved (stale / cross-env).
|
||||
*/
|
||||
currentRunStatus: TaskRunStatus | undefined;
|
||||
/** `Date.now()` at the time of derivation. */
|
||||
@@ -38,7 +38,7 @@ export function deriveSessionStatus(input: DeriveSessionStatusInput): SessionDis
|
||||
}
|
||||
|
||||
const hasLiveRun =
|
||||
input.currentRunId != null &&
|
||||
input.hasCurrentRun &&
|
||||
input.currentRunStatus !== undefined &&
|
||||
!isFinalRunStatus(input.currentRunStatus);
|
||||
|
||||
|
||||
+2
-2
@@ -119,7 +119,7 @@ export default function Page() {
|
||||
const status = deriveSessionStatus({
|
||||
closedAt: session.closedAt ? new Date(session.closedAt) : null,
|
||||
expiresAt: session.expiresAt ? new Date(session.expiresAt) : null,
|
||||
currentRunId: session.currentRun?.friendlyId ?? null,
|
||||
hasCurrentRun: session.currentRun != null,
|
||||
currentRunStatus: session.currentRun?.status,
|
||||
now: Date.now(),
|
||||
});
|
||||
@@ -791,7 +791,7 @@ function OverviewTab({
|
||||
<SessionStatusCombo status={status} />
|
||||
</Property.Value>
|
||||
</Property.Item>
|
||||
{status === "ACTIVE" && (
|
||||
{(status === "ACTIVE" || status === "IDLE") && (
|
||||
<Dialog key={`close-${session.friendlyId}`}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="danger/small">Close session…</Button>
|
||||
|
||||
@@ -99,7 +99,10 @@ const { id, runId, publicAccessToken, isCached } = await sessions.start({
|
||||
type: "chat.agent",
|
||||
externalId: chatId,
|
||||
taskIdentifier: "my-chat",
|
||||
// Top-level tags live on the Session row and are what `sessions.list({ tag })` filters on.
|
||||
tags: [`chat:${chatId}`],
|
||||
triggerConfig: {
|
||||
// triggerConfig.tags tag each run the session schedules, not the session row.
|
||||
tags: [`chat:${chatId}`],
|
||||
basePayload: { /* whatever your task's payload shape is */ },
|
||||
},
|
||||
@@ -153,7 +156,7 @@ Cursor-paginated list of Sessions in the current environment. Returns a `CursorP
|
||||
```ts
|
||||
for await (const s of sessions.list({
|
||||
type: "chat.agent",
|
||||
tag: `user:${userId}`,
|
||||
tag: `chat:${chatId}`,
|
||||
status: "ACTIVE",
|
||||
limit: 50,
|
||||
})) {
|
||||
|
||||
Reference in New Issue
Block a user