feat(server): add typed list session gql (#12979)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Introduced new API endpoints and GraphQL queries to retrieve Copilot
chat sessions by workspace, document, and pinned status, with detailed
session and message information.
* Added support for filtering and querying Copilot chat histories with
new options such as pinned status and message ordering.

* **Bug Fixes**
* Improved filtering logic for listing and retrieving chat sessions,
ensuring accurate results for workspace, document, and pinned session
queries.

* **Tests**
* Expanded and refactored test coverage for session listing, filtering,
and new query options to ensure reliability and correctness of Copilot
session retrieval.
* Updated snapshot data to reflect new session types and filtering
capabilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-07-01 19:31:37 +08:00
committed by GitHub
parent 6e9487a9e1
commit 0326da0806
13 changed files with 704 additions and 152 deletions

View File

@@ -285,38 +285,44 @@ export class CopilotSessionModel extends BaseModel {
}
async list(options: ListSessionOptions) {
const { userId, sessionId, workspaceId, docId } = options;
const { userId, sessionId, workspaceId, docId, action, fork } = options;
function getNullCond<T>(
maybeBool: boolean | undefined,
wrap: (ret: { not: null } | null) => T = ret => ret as T
): T | undefined {
return maybeBool === true
? wrap({ not: null })
: maybeBool === false
? wrap(null)
: undefined;
}
function getEqCond<T>(maybeValue: T | undefined): T | undefined {
return maybeValue !== undefined ? maybeValue : undefined;
}
const conditions: Prisma.AiSessionWhereInput['OR'] = [
{
userId,
workspaceId,
docId: docId ?? null,
id: sessionId ? { equals: sessionId } : undefined,
docId: getEqCond(docId),
id: getEqCond(sessionId),
deletedAt: null,
prompt:
typeof options.action === 'boolean'
? options.action
? { action: { not: null } }
: { action: null }
: undefined,
parentSessionId:
typeof options.fork === 'boolean'
? options.fork
? { not: null }
: null
: undefined,
pinned: getEqCond(options.pinned),
prompt: getNullCond(fork, ret => ({ action: ret })),
parentSessionId: getNullCond(fork),
},
];
if (!options?.action && options?.fork) {
if (!action && fork) {
// query forked sessions from other users
// only query forked session if fork == true and action == false
conditions.push({
userId: { not: userId },
workspaceId: workspaceId,
docId: docId ?? null,
id: sessionId ? { equals: sessionId } : undefined,
id: getEqCond(sessionId),
prompt: { action: null },
// should only find forked session
parentSessionId: { not: null },