function wrapNextHandler({ shim, output, segment, transaction, request, metadata, tags }) {
  shim.wrap(output, 'next', function wrapIterator(shim, orig) {
    let content = ''
    return async function wrappedIterator() {
      try {
        const result = await orig.apply(this, arguments)
        // only create Llm events when stream iteration is done
        if (result?.done) {
          recordChatCompletionEvents({
            transaction,
            segment,
            messages: [content],
            events: [request, content],
            metadata,
            tags,
            shim
          })
        } else {
          content += result.value
        }
        return result
      } catch (error) {
        recordChatCompletionEvents({
          transaction,
          segment,
          messages: [content],
          events: [request, content],
          metadata,
          tags,
          err: error,
          shim
        })
        throw error
      } finally {
        // update segment duration on every stream iteration to extend
        // the timer
        segment.touch()
      }
    }
  })
}
Wraps the next method on the IterableReadableStream. It will also record the Llm
events when the stream is done processing.

@param {object} params function params
@param {Shim} params.shim shim instance
@param {TraceSegment} params.segment active segment
@param {function} params.output IterableReadableStream
@param {string} params.request the prompt message
@param {object} params.metadata metadata for the call
@param {Array} params.tags tags for the call
@param {Transaction} params.transaction active transaction