Files
bb8d4f30e7 feat(chat): add experimental Pi classroom runtime behind a flag (#914)
* feat(chat): add experimental Pi classroom runtime

* fix(chat): harden Pi whiteboard action sequencing

* style(chat): format session retirement flow

* style(playback): format async scene transition

* fix(chat): retire actions on session errors

* fix(chat): close Pi runtime lifecycle gaps

* fix(chat): avoid replaying historical whiteboard actions

* fix(chat): prevent Pi structured-output residue from leaking and inflating turns

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(chat): expose whiteboard element/line ids and bound code-line context

Surface each element's id (and code line ids) in the Pi whiteboard context so
later child agents can target wb_delete / wb_edit_code, and cap the rendered
code lines with a shared character budget so a code-heavy board cannot grow the
prompt without bound. Return only the current turn's whiteboard ledger from the
Pi director loop instead of carrying history forward across requests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(chat): bound Pi whiteboard code context

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(chat): prioritize newer persisted whiteboard code in budget

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(chat): enforce whiteboard boundaries across Pi sessions

* feat(chat): refine soft-closing discussion controls

* fix(chat): make whiteboard clearing model-directed

---------

Co-authored-by: apple <apple@GigideMacBook-Air.local>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: LING-6150 <duan.lin@northeastern.edu>
2026-07-17 11:22:02 +08:00

45 lines
1.6 KiB
TypeScript

import type { EngineMode } from './types';
/**
* Where a chat-session cleanup originated. A confirmed or timed-out soft close
* may auto-resume an interrupted lecture; other sources must not.
*/
export type CleanupSource =
| 'soft_close_enter'
| 'soft_close_confirmed'
| 'soft_close_timeout'
| 'manual_stop'
| 'scene_switch'
| 'error'
| 'turn_complete';
export interface AutoResumeArgs {
/** Which cleanup path is running. */
source: CleanupSource;
/** Director-provided reason the Q&A/discussion ended, if any. */
endReason?: string;
/** Whether this session interrupted an active lecture (read before cleanup). */
hadLectureInterruption: boolean;
/** Engine mode AFTER cleanup restored the saved lecture position. */
engineMode: EngineMode;
/** Whether the course has no more content to play. */
isExhausted: boolean;
/** Whether playback already reached completion. */
playbackCompleted: boolean;
}
/**
* Decide whether an ended Q&A/discussion should auto-resume the lecture it
* interrupted. Pure and conservative: it only returns true for the narrow
* "completed soft close after a satisfied/back-to-lesson Q&A" case, and
* requires the engine to be idle with content still remaining.
*/
export function shouldAutoResumeLecture(args: AutoResumeArgs): boolean {
if (args.source !== 'soft_close_confirmed' && args.source !== 'soft_close_timeout') return false;
if (!args.hadLectureInterruption) return false;
if (args.endReason !== 'user_done' && args.endReason !== 'back_to_lesson') return false;
if (args.engineMode !== 'idle') return false;
if (args.isExhausted || args.playbackCompleted) return false;
return true;
}