Skip to content

Commit c7701ba

Browse files
committed
Expose session context in listSessions and add filtering
Adds SessionContext to SessionMetadata so SDK consumers can see the working directory and repository information for each session. Also adds optional filter parameter to listSessions() for filtering by context fields (cwd, gitRoot, repository, branch). Fixes #413 Fixes #200
1 parent ccb7d5f commit c7701ba

7 files changed

Lines changed: 97 additions & 2 deletions

File tree

cookbook/nodejs/multiple-sessions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ console.log(session.sessionId); // "user-123-chat"
6363
const sessions = await client.listSessions();
6464
console.log(sessions);
6565
// [{ sessionId: "user-123-chat", ... }, ...]
66+
67+
// Sessions include context (cwd, git info) from when they were created
68+
for (const s of sessions) {
69+
console.log(`${s.sessionId} - ${s.context?.cwd ?? "unknown"}`);
70+
}
6671
```
6772
6873
## Deleting sessions

cookbook/nodejs/persisting-sessions.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ console.log(sessions);
6464
// { sessionId: "user-123-conversation", ... },
6565
// { sessionId: "user-456-conversation", ... },
6666
// ]
67+
68+
// Each session includes context from when it was created
69+
for (const session of sessions) {
70+
console.log(`Session: ${session.sessionId}`);
71+
if (session.context) {
72+
console.log(` Directory: ${session.context.cwd}`);
73+
console.log(` Repository: ${session.context.repository}`);
74+
console.log(` Branch: ${session.context.branch}`);
75+
}
76+
}
6777
```
6878
6979
### Deleting a session permanently

nodejs/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,22 @@ Get current connection state.
111111

112112
List all available sessions.
113113

114+
**SessionMetadata:**
115+
116+
- `sessionId: string` - Unique session identifier
117+
- `startTime: Date` - When the session was created
118+
- `modifiedTime: Date` - When the session was last modified
119+
- `summary?: string` - Optional session summary
120+
- `isRemote: boolean` - Whether the session is remote
121+
- `context?: SessionContext` - Working directory context from session creation
122+
123+
**SessionContext:**
124+
125+
- `cwd: string` - Working directory where the session was created
126+
- `gitRoot?: string` - Git repository root (if in a git repo)
127+
- `repository?: string` - GitHub repository in "owner/repo" format
128+
- `branch?: string` - Current git branch
129+
114130
##### `deleteSession(sessionId: string): Promise<void>`
115131

116132
Delete a session and its data from disk.

nodejs/src/client.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import type {
3030
ResumeSessionConfig,
3131
SessionConfig,
3232
SessionEvent,
33+
SessionListFilter,
3334
SessionMetadata,
3435
Tool,
3536
ToolCallRequestPayload,
@@ -749,19 +750,25 @@ export class CopilotClient {
749750
* }
750751
* ```
751752
*/
752-
async listSessions(): Promise<SessionMetadata[]> {
753+
async listSessions(filter?: SessionListFilter): Promise<SessionMetadata[]> {
753754
if (!this.connection) {
754755
throw new Error("Client not connected");
755756
}
756757

757-
const response = await this.connection.sendRequest("session.list", {});
758+
const response = await this.connection.sendRequest("session.list", { filter });
758759
const { sessions } = response as {
759760
sessions: Array<{
760761
sessionId: string;
761762
startTime: string;
762763
modifiedTime: string;
763764
summary?: string;
764765
isRemote: boolean;
766+
context?: {
767+
cwd: string;
768+
gitRoot?: string;
769+
repository?: string;
770+
branch?: string;
771+
};
765772
}>;
766773
};
767774

@@ -771,6 +778,7 @@ export class CopilotClient {
771778
modifiedTime: new Date(s.modifiedTime),
772779
summary: s.summary,
773780
isRemote: s.isRemote,
781+
context: s.context,
774782
}));
775783
}
776784

nodejs/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type {
3535
SessionEventHandler,
3636
SessionEventPayload,
3737
SessionEventType,
38+
SessionListFilter,
3839
SessionMetadata,
3940
SystemMessageAppendConfig,
4041
SystemMessageConfig,

nodejs/src/types.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,34 @@ export type SessionEventHandler = (event: SessionEvent) => void;
833833
*/
834834
export type ConnectionState = "disconnected" | "connecting" | "connected" | "error";
835835

836+
/**
837+
* Working directory context for a session
838+
*/
839+
export interface SessionContext {
840+
/** Working directory where the session was created */
841+
cwd: string;
842+
/** Git repository root (if in a git repo) */
843+
gitRoot?: string;
844+
/** GitHub repository in "owner/repo" format */
845+
repository?: string;
846+
/** Current git branch */
847+
branch?: string;
848+
}
849+
850+
/**
851+
* Filter options for listing sessions
852+
*/
853+
export interface SessionListFilter {
854+
/** Filter by exact cwd match */
855+
cwd?: string;
856+
/** Filter by git root */
857+
gitRoot?: string;
858+
/** Filter by repository (owner/repo format) */
859+
repository?: string;
860+
/** Filter by branch */
861+
branch?: string;
862+
}
863+
836864
/**
837865
* Metadata about a session
838866
*/
@@ -842,6 +870,8 @@ export interface SessionMetadata {
842870
modifiedTime: Date;
843871
summary?: string;
844872
isRemote: boolean;
873+
/** Working directory context (cwd, git info) from session creation */
874+
context?: SessionContext;
845875
}
846876

847877
/**

nodejs/test/e2e/session.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,31 @@ describe("Sessions", async () => {
2222
await expect(() => session.getMessages()).rejects.toThrow(/Session not found/);
2323
});
2424

25+
it("should list sessions with context field", async () => {
26+
// Create a new session
27+
const session = await client.createSession();
28+
expect(session.sessionId).toMatch(/^[a-f0-9-]+$/);
29+
30+
// List sessions and find the one we just created
31+
const sessions = await client.listSessions();
32+
const ourSession = sessions.find((s) => s.sessionId === session.sessionId);
33+
34+
expect(ourSession).toBeDefined();
35+
expect(ourSession?.context).toBeDefined();
36+
// cwd should be set to some path
37+
expect(ourSession?.context?.cwd).toMatch(/^(\/|[A-Za-z]:)/);
38+
// gitRoot, repository, and branch are optional
39+
if (ourSession?.context?.gitRoot) {
40+
expect(typeof ourSession.context.gitRoot).toBe("string");
41+
}
42+
if (ourSession?.context?.repository) {
43+
expect(typeof ourSession.context.repository).toBe("string");
44+
}
45+
if (ourSession?.context?.branch) {
46+
expect(typeof ourSession.context.branch).toBe("string");
47+
}
48+
});
49+
2550
it("should have stateful conversation", async () => {
2651
const session = await client.createSession();
2752
const assistantMessage = await session.sendAndWait({ prompt: "What is 1+1?" });

0 commit comments

Comments
 (0)