Files
openmaic/OpenMAIC/lib/chat/pi/tools/close-session.ts
2026-08-16 14:58:47 +08:00

75 lines
2.3 KiB
TypeScript

import type { AgentTool } from '@earendil-works/pi-agent-core';
import { Type, type Static } from 'typebox';
const CloseSessionParams = Type.Object({
endReason: Type.Optional(
Type.Union(
[
Type.Literal('user_goodbye'),
Type.Literal('user_done'),
Type.Literal('back_to_lesson'),
Type.Literal('lesson_complete'),
],
{
description:
'Machine-readable reason for ending the classroom session. Use user_done for satisfied/no-more-questions acknowledgments and back_to_lesson for resume-lesson requests.',
},
),
),
});
type CloseSessionParams = Static<typeof CloseSessionParams>;
export function buildCloseSessionTool(opts: {
closeSession: (data: { endReason?: string }) => Promise<boolean>;
canCloseSession?: () => boolean;
isUserCued?: () => boolean;
}): AgentTool<typeof CloseSessionParams> {
return {
name: 'close_session',
label: 'Close session',
description:
'Explicitly close the classroom session after a clear ending, goodbye, or lesson wrap-up.',
parameters: CloseSessionParams,
executionMode: 'sequential',
execute: async (_toolCallId: string, params: CloseSessionParams) => {
if (opts.isUserCued?.()) {
return {
content: [
{
type: 'text',
text: 'The user has already been invited to continue, so the session remains open.',
},
],
details: { emitted: false, skipped: true, reason: 'user_already_cued' },
};
}
if (opts.canCloseSession && !opts.canCloseSession()) {
return {
content: [
{
type: 'text',
text: 'Call a classroom agent for a short, visible closing line before closing the session.',
},
],
details: { emitted: false, skipped: true, reason: 'no_visible_agent_turn' },
};
}
const emitted = await opts.closeSession({ endReason: params.endReason });
return {
content: [
{
type: 'text',
text: emitted
? 'The classroom session has been marked for closure.'
: 'The classroom session was already marked for closure.',
},
],
details: { emitted },
};
},
};
}