fix(coding-agent): emit session name changes to extensions
This commit is contained in:
@@ -322,6 +322,9 @@ user sends another prompt ◄─────────────────
|
||||
├─► session_start { reason: "fork", previousSessionFile }
|
||||
└─► resources_discover { reason: "startup" }
|
||||
|
||||
/name or pi.setSessionName()
|
||||
└─► session_info_changed
|
||||
|
||||
/compact or auto-compaction
|
||||
├─► session_before_compact (can cancel or customize)
|
||||
└─► session_compact
|
||||
@@ -395,6 +398,17 @@ pi.on("session_start", async (event, ctx) => {
|
||||
});
|
||||
```
|
||||
|
||||
#### session_info_changed
|
||||
|
||||
Fired when the current session display name is set via `/name`, RPC, or `pi.setSessionName()`.
|
||||
|
||||
```typescript
|
||||
pi.on("session_info_changed", async (event, ctx) => {
|
||||
// event.name - current normalized name, or undefined if cleared
|
||||
ctx.ui.notify(`Session renamed: ${event.name ?? "(none)"}`, "info");
|
||||
});
|
||||
```
|
||||
|
||||
#### session_before_switch
|
||||
|
||||
Fired before starting a new session (`/new`) or switching sessions (`/resume`).
|
||||
|
||||
@@ -2683,7 +2683,9 @@ export class AgentSession {
|
||||
*/
|
||||
setSessionName(name: string): void {
|
||||
this.sessionManager.appendSessionInfo(name);
|
||||
this._emit({ type: "session_info_changed", name: this.sessionManager.getSessionName() });
|
||||
const event = { type: "session_info_changed", name: this.sessionManager.getSessionName() } as const;
|
||||
this._emit(event);
|
||||
void this._extensionRunner.emit(event);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@@ -128,6 +128,7 @@ export type {
|
||||
SessionBeforeTreeResult,
|
||||
SessionCompactEvent,
|
||||
SessionEvent,
|
||||
SessionInfoChangedEvent,
|
||||
SessionShutdownEvent,
|
||||
// Events - Session
|
||||
SessionStartEvent,
|
||||
|
||||
@@ -551,6 +551,13 @@ export interface SessionStartEvent {
|
||||
previousSessionFile?: string;
|
||||
}
|
||||
|
||||
/** Fired when the current session metadata changes. */
|
||||
export interface SessionInfoChangedEvent {
|
||||
type: "session_info_changed";
|
||||
/** Current normalized session name. Undefined when the name is cleared. */
|
||||
name: string | undefined;
|
||||
}
|
||||
|
||||
/** Fired before switching to another session (can be cancelled) */
|
||||
export interface SessionBeforeSwitchEvent {
|
||||
type: "session_before_switch";
|
||||
@@ -630,6 +637,7 @@ export interface SessionTreeEvent {
|
||||
|
||||
export type SessionEvent =
|
||||
| SessionStartEvent
|
||||
| SessionInfoChangedEvent
|
||||
| SessionBeforeSwitchEvent
|
||||
| SessionBeforeForkEvent
|
||||
| SessionBeforeCompactEvent
|
||||
@@ -1133,6 +1141,7 @@ export interface ExtensionAPI {
|
||||
on(event: "project_trust", handler: ProjectTrustHandler): void;
|
||||
on(event: "resources_discover", handler: ExtensionHandler<ResourcesDiscoverEvent, ResourcesDiscoverResult>): void;
|
||||
on(event: "session_start", handler: ExtensionHandler<SessionStartEvent>): void;
|
||||
on(event: "session_info_changed", handler: ExtensionHandler<SessionInfoChangedEvent>): void;
|
||||
on(
|
||||
event: "session_before_switch",
|
||||
handler: ExtensionHandler<SessionBeforeSwitchEvent, SessionBeforeSwitchResult>,
|
||||
|
||||
@@ -122,6 +122,7 @@ export type {
|
||||
SessionBeforeSwitchEvent,
|
||||
SessionBeforeTreeEvent,
|
||||
SessionCompactEvent,
|
||||
SessionInfoChangedEvent,
|
||||
SessionShutdownEvent,
|
||||
SessionStartEvent,
|
||||
SessionTreeEvent,
|
||||
|
||||
@@ -37,4 +37,25 @@ describe("regression #3686: session name changes emit an event", () => {
|
||||
expect(harness.sessionManager.getSessionName()).toBe("from extension");
|
||||
expect(harness.eventsOfType("session_info_changed").map((event) => event.name)).toEqual(["from extension"]);
|
||||
});
|
||||
|
||||
it("emits session_info_changed to extensions", async () => {
|
||||
let api: ExtensionAPI | undefined;
|
||||
const events: Array<{ name: string | undefined }> = [];
|
||||
const harness = await createHarness({
|
||||
extensionFactories: [
|
||||
(pi) => {
|
||||
api = pi;
|
||||
pi.on("session_info_changed", (event) => {
|
||||
events.push({ name: event.name });
|
||||
});
|
||||
},
|
||||
],
|
||||
});
|
||||
harnesses.push(harness);
|
||||
|
||||
api?.setSessionName("first");
|
||||
harness.session.setSessionName("second");
|
||||
|
||||
expect(events).toEqual([{ name: "first" }, { name: "second" }]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user