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
18 changes: 18 additions & 0 deletions core/src/sessions/base_session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export interface ListSessionsRequest {
appName: string;
/** The ID of the user. */
userId: string;
/** Maximum number of sessions to return. */
limit?: number;
/** Zero-based index of the first session to return. Ignored if `page` is set. */
offset?: number;
/** 1-based page number. Requires `limit`. Takes precedence over `offset`. */
page?: number;
/** Sort direction by last update time. No ordering is applied if omitted. */
order?: 'asc' | 'desc';
}

/**
Expand Down Expand Up @@ -85,10 +93,20 @@ export interface AppendEventRequest {
* The response of listing sessions.
*
* The events and states are not set within each Session object.
* When no pagination params were requested, `page` is 1, `limit` equals
* `totalItems`, and `totalPages` is 1 (or 0 when there are no sessions).
*/
export interface ListSessionsResponse {
/** A list of sessions. */
sessions: Session[];
/** Current page number (1-based). */
page: number;
/** Page size used. Equals `totalItems` when no limit was requested. */
limit: number;
/** Total number of sessions matching the request. */
totalItems: number;
/** Total number of pages. */
totalPages: number;
}

/**
Expand Down
64 changes: 62 additions & 2 deletions core/src/sessions/database_session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ export class DatabaseSessionService extends BaseSessionService {
async listSessions({
appName,
userId,
limit,
offset,
page,
order,
}: ListSessionsRequest): Promise<ListSessionsResponse> {
await this.init();
const em = this.orm!.em.fork();
Expand All @@ -263,7 +267,63 @@ export class DatabaseSessionService extends BaseSessionService {
where.userId = userId;
}

const storageSessions = await em.find(StorageSession, where);
const orderBy =
order === 'asc'
? {updateTime: 'ASC' as const, id: 'ASC' as const}
: order === 'desc'
? {updateTime: 'DESC' as const, id: 'ASC' as const}
: undefined;

let storageSessions;
let paginationMeta: Pick<
ListSessionsResponse,
'page' | 'limit' | 'totalItems' | 'totalPages'
>;

if (limit !== undefined) {
const totalItems = await em.count(StorageSession, where);
const totalPages = limit === 0 ? 0 : Math.ceil(totalItems / limit);

let effectiveOffset: number;
let effectivePage: number;
if (page !== undefined) {
effectiveOffset = (page - 1) * limit;
effectivePage = page;
} else {
effectiveOffset = offset ?? 0;
effectivePage =
limit === 0 ? 1 : Math.floor(effectiveOffset / limit) + 1;
}

storageSessions = await em.find(StorageSession, where, {
orderBy,
limit,
offset: effectiveOffset,
});
paginationMeta = {page: effectivePage, limit, totalItems, totalPages};
} else if (offset) {
const totalItems = await em.count(StorageSession, where);
storageSessions = await em.find(StorageSession, where, {
orderBy,
offset,
});
paginationMeta = {
page: 1,
limit: totalItems,
totalItems,
totalPages: totalItems === 0 ? 0 : 1,
};
} else {
storageSessions = await em.find(StorageSession, where, {orderBy});
const totalItems = storageSessions.length;
paginationMeta = {
page: 1,
limit: totalItems,
totalItems,
totalPages: totalItems === 0 ? 0 : 1,
};
}

const appStateModel = await em.findOne(StorageAppState, {appName});
const appState = appStateModel?.state || {};
const userStateMap: Record<string, Record<string, unknown>> = {};
Expand Down Expand Up @@ -291,7 +351,7 @@ export class DatabaseSessionService extends BaseSessionService {
});
});

return {sessions};
return {sessions, ...paginationMeta};
}

async deleteSession({
Expand Down
80 changes: 75 additions & 5 deletions core/src/sessions/in_memory_session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,40 @@ export class InMemorySessionService extends BaseSessionService {
listSessions({
appName,
userId,
limit,
offset,
page,
order,
}: ListSessionsRequest): Promise<ListSessionsResponse> {
if (!this.sessions[appName] || !this.sessions[appName][userId]) {
return Promise.resolve({sessions: []});
if (limit !== undefined) {
const effectiveOffset =
page !== undefined ? (page - 1) * limit : (offset ?? 0);
const effectivePage =
page !== undefined
? page
: limit === 0
? 1
: Math.floor(effectiveOffset / limit) + 1;
return Promise.resolve({
sessions: [],
page: effectivePage,
limit,
totalItems: 0,
totalPages: 0,
});
}
return Promise.resolve({
sessions: [],
page: 1,
limit: 0,
totalItems: 0,
totalPages: 0,
});
}

const sessionsWithoutEvents: Session[] = [];
for (const session of Object.values(this.sessions[appName][userId])) {
sessionsWithoutEvents.push(
const all: Session[] = Object.values(this.sessions[appName][userId]).map(
(session) =>
createSession({
id: session.id,
appName: session.appName,
Expand All @@ -150,10 +176,54 @@ export class InMemorySessionService extends BaseSessionService {
events: [],
lastUpdateTime: session.lastUpdateTime,
}),
);

if (order === 'asc') {
all.sort(
(a, b) =>
a.lastUpdateTime - b.lastUpdateTime || a.id.localeCompare(b.id),
);
} else if (order === 'desc') {
all.sort(
(a, b) =>
b.lastUpdateTime - a.lastUpdateTime || a.id.localeCompare(b.id),
);
}

if (limit === undefined) {
const totalItems = all.length;
const sliced = offset ? all.slice(offset) : all;
return Promise.resolve({
sessions: sliced,
page: 1,
limit: totalItems,
totalItems,
totalPages: totalItems === 0 ? 0 : 1,
});
}

const totalItems = all.length;
const totalPages = limit === 0 ? 0 : Math.ceil(totalItems / limit);

let effectiveOffset: number;
let effectivePage: number;
if (page !== undefined) {
effectiveOffset = (page - 1) * limit;
effectivePage = page;
} else {
effectiveOffset = offset ?? 0;
effectivePage = limit === 0 ? 1 : Math.floor(effectiveOffset / limit) + 1;
}

return Promise.resolve({sessions: sessionsWithoutEvents});
const paginated = all.slice(effectiveOffset, effectiveOffset + limit);

return Promise.resolve({
sessions: paginated,
page: effectivePage,
limit,
totalItems,
totalPages,
});
}

async deleteSession({
Expand Down
49 changes: 48 additions & 1 deletion core/src/sessions/vertex_ai_session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ export class VertexAiSessionService extends BaseSessionService {
async listSessions({
appName,
userId,
limit,
offset,
page,
order,
}: ListSessionsRequest): Promise<ListSessionsResponse> {
const reasoningEngineId = this.getReasoningEngineId(appName);
const adkSessions: Session[] = [];
Expand Down Expand Up @@ -278,7 +282,50 @@ export class VertexAiSessionService extends BaseSessionService {
pageToken = (response as {nextPageToken?: string}).nextPageToken;
} while (pageToken);

return {sessions: adkSessions};
if (order === 'asc') {
adkSessions.sort(
(a, b) =>
a.lastUpdateTime - b.lastUpdateTime || a.id.localeCompare(b.id),
);
} else if (order === 'desc') {
adkSessions.sort(
(a, b) =>
b.lastUpdateTime - a.lastUpdateTime || a.id.localeCompare(b.id),
);
}

if (limit === undefined) {
const totalItems = adkSessions.length;
const sliced = offset ? adkSessions.slice(offset) : adkSessions;
return {
sessions: sliced,
page: 1,
limit: totalItems,
totalItems,
totalPages: totalItems === 0 ? 0 : 1,
};
}

const totalItems = adkSessions.length;
const totalPages = limit === 0 ? 0 : Math.ceil(totalItems / limit);

let effectiveOffset: number;
let effectivePage: number;
if (page !== undefined) {
effectiveOffset = (page - 1) * limit;
effectivePage = page;
} else {
effectiveOffset = offset ?? 0;
effectivePage = limit === 0 ? 1 : Math.floor(effectiveOffset / limit) + 1;
}

return {
sessions: adkSessions.slice(effectiveOffset, effectiveOffset + limit),
page: effectivePage,
limit,
totalItems,
totalPages,
};
}

async deleteSession({
Expand Down
Loading