package llmfs import ( "io" "github.com/NERVsystems/llm9p/internal/llm" "github.com/NERVsystems/llm9p/internal/protocol" ) // SessionStreamFile is the stream file for a specific session: /n/llm/N/stream // Read blocks until the next chunk is available, returning chunks as they arrive // and io.EOF when generation completes (or no generation is active). type SessionStreamFile struct { *protocol.BaseFile sm *llm.SessionManager id int } // NewSessionStreamFile creates a stream file for the given session. func NewSessionStreamFile(sm *llm.SessionManager, id int) *SessionStreamFile { return &SessionStreamFile{ BaseFile: protocol.NewBaseFile("stream", 0444), sm: sm, id: id, } } // Read blocks until the next text chunk is available and copies it into p. // Returns io.EOF when generation completes or no generation is active. // The offset parameter is ignored — this is a streaming file, not seekable. func (f *SessionStreamFile) Read(p []byte, offset int64) (int, error) { session := f.sm.Get(f.id) if session == nil { return 0, protocol.ErrNotFound } ch := session.GetStreamCh() if ch == nil { // No active generation. return 0, io.EOF } chunk, ok := <-ch if !ok { // Channel closed: generation complete. return 0, io.EOF } n := copy(p, chunk) return n, nil }