feat(hooks): implement session:start and session:end lifecycle events
- Add session:end event triggered before /new or /reset clears the session - Add session:start event triggered when a new session begins - Update docs to reflect implemented session lifecycle events Events include context for: - sessionEntry, sessionId, sessionFile - commandSource, senderId - reason (for session:end) / isReset (for session:start) - cfg for hook access to config
This commit is contained in:
parent
01e0d3a320
commit
4167069fbc
@ -235,6 +235,15 @@ Triggered when the gateway starts:
|
||||
|
||||
- **`gateway:startup`**: After channels start and hooks are loaded
|
||||
|
||||
### Session Events
|
||||
|
||||
Triggered during session lifecycle:
|
||||
|
||||
- **`session:start`**: When a new session begins (after `/new`, `/reset`, or first message from a new sender)
|
||||
- Context includes: `sessionEntry`, `sessionId`, `sessionFile`, `commandSource`, `senderId`, `isReset` (true if triggered by reset command), `cfg`
|
||||
- **`session:end`**: When a session ends (before `/new` or `/reset` clears the session)
|
||||
- Context includes: `sessionEntry` (previous session), `sessionId`, `sessionFile`, `commandSource`, `senderId`, `reason` ("reset"), `cfg`
|
||||
|
||||
### Tool Result Hooks (Plugin API)
|
||||
|
||||
These hooks are not event-stream listeners; they let plugins synchronously adjust tool results before Moltbot persists them.
|
||||
@ -244,9 +253,6 @@ These hooks are not event-stream listeners; they let plugins synchronously adjus
|
||||
### Future Events
|
||||
|
||||
Planned event types:
|
||||
|
||||
- **`session:start`**: When a new session begins
|
||||
- **`session:end`**: When a session ends
|
||||
- **`agent:error`**: When an agent encounters an error
|
||||
- **`message:sent`**: When a message is sent
|
||||
- **`message:received`**: When a message is received
|
||||
|
||||
@ -71,6 +71,21 @@ export async function handleCommands(params: HandleCommandsParams): Promise<Comm
|
||||
// Trigger internal hook for reset/new commands
|
||||
if (resetRequested && params.command.isAuthorizedSender) {
|
||||
const commandAction = resetMatch?.[1] ?? "new";
|
||||
|
||||
// Trigger session:end for the previous session before reset
|
||||
if (params.previousSessionEntry) {
|
||||
const sessionEndEvent = createInternalHookEvent("session", "end", params.sessionKey ?? "", {
|
||||
sessionEntry: params.previousSessionEntry,
|
||||
sessionId: params.previousSessionEntry.sessionId,
|
||||
sessionFile: params.previousSessionEntry.sessionFile,
|
||||
commandSource: params.command.surface,
|
||||
senderId: params.command.senderId,
|
||||
reason: "reset", // Session ended due to /new or /reset command
|
||||
cfg: params.cfg,
|
||||
});
|
||||
await triggerInternalHook(sessionEndEvent);
|
||||
}
|
||||
|
||||
const hookEvent = createInternalHookEvent("command", commandAction, params.sessionKey ?? "", {
|
||||
sessionEntry: params.sessionEntry,
|
||||
previousSessionEntry: params.previousSessionEntry,
|
||||
|
||||
@ -18,6 +18,7 @@ import { resolveDefaultModel } from "./directive-handling.js";
|
||||
import { resolveReplyDirectives } from "./get-reply-directives.js";
|
||||
import { handleInlineActions } from "./get-reply-inline-actions.js";
|
||||
import { runPreparedReply } from "./get-reply-run.js";
|
||||
import { createInternalHookEvent, triggerInternalHook } from "../../hooks/internal-hooks.js";
|
||||
import { finalizeInboundContext } from "./inbound-context.js";
|
||||
import { initSessionState } from "./session.js";
|
||||
import { applyResetModelOverride } from "./session-reset-model.js";
|
||||
@ -126,6 +127,20 @@ export async function getReplyFromConfig(
|
||||
bodyStripped,
|
||||
} = sessionState;
|
||||
|
||||
// Trigger session:start for new sessions
|
||||
if (isNewSession) {
|
||||
const sessionStartEvent = createInternalHookEvent("session", "start", sessionKey, {
|
||||
sessionEntry,
|
||||
sessionId,
|
||||
sessionFile: sessionEntry.sessionFile,
|
||||
commandSource: finalized.Surface ?? finalized.Provider,
|
||||
senderId: finalized.From,
|
||||
isReset: resetTriggered, // True if session started due to /new or /reset
|
||||
cfg,
|
||||
});
|
||||
await triggerInternalHook(sessionStartEvent);
|
||||
}
|
||||
|
||||
await applyResetModelOverride({
|
||||
cfg,
|
||||
resetTriggered,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user