constructor({ agent, kvPairs = [], logger = defaultLogger }) {
    if (Object.prototype.toString.call(agent) !== '[object Agent]') {
      throw Error('agent must be an agent instance')
    }

    this.#agent = agent
    this.#logger = logger

    const trustedKey = this.#agent.config.trusted_account_key
    const hasTrustKey = Boolean(trustedKey)
    const expectedNrKey = `${trustedKey}@nr`

    if (hasTrustKey === false) {
      logger.debug(
        'Unable to accept any New Relic tracestate list members. ' +
        'Missing trusted_account_key. ' +
        'This may occur if a trace is received prior to the agent fully starting.'
      )
      this.#agent.recordSupportability('TraceContext/TraceState/Accept/Exception')
    }

    let nrTraceStateValue = null
    const vendors = new Set()
    const listMembers = new Map()
    for (const listMember of kvPairs) {
      const parts = listMember.split('=', 2).filter(v => Boolean(v))
      if (parts.length !== 2) {
        this.#logger.debug('Unable to parse tracestate list members.')
        this.#agent.recordSupportability('TraceContext/TraceState/Parse/Exception/ListMember')
        throw Error(`list member is not in parseable format: ${listMember}`)
      }

      const [vendorKey, vendorValue] = parts
      if (hasTrustKey === true && vendorKey === expectedNrKey) {
        // We do not add New Relic states to the vendors list. It's not clear
        // _why_, but the original tracestate implementation made this decision
        // so we are propagating it. ~ James Sumners 2025-03-21

        // We only want the first found New Relic value. Any subsequent entries
        // are to be considered invalid.
        nrTraceStateValue = nrTraceStateValue ?? vendorValue
      } else {
        vendors.add(vendorKey)
        listMembers.set(vendorKey, vendorValue)
      }
    }

    let intrinsics
    if (nrTraceStateValue) {
      intrinsics = new TracestateIntrinsics()
      const values = nrTraceStateValue.split('-').map(v => v === '' ? null : v)
      intrinsics.version = values[0]
      intrinsics.parentType = values[1]
      intrinsics.accountId = values[2]
      intrinsics.appId = values[3]
      intrinsics.spanId = values[4]
      intrinsics.transactionId = values[5]
      intrinsics.sampled = values[6]
      intrinsics.priority = values[7]
      intrinsics.timestamp = values[8]
    } else {
      this.#agent.recordSupportability('TraceContext/TraceState/NoNrEntry')
    }

    Object.defineProperties(this, {
      vendors: {
        enumerable: true,
        // Ideally, we'd set it to an empty array if there are not any vendors
        // in the list. But we have test code, particularly in the cross agents
        // test suite, that looks for a `null` value in that case. Instead of
        // trying to trace down all of those possible locations, we propagate
        // the original design. ~ James Sumners 2025-03-21
        value: vendors.size > 0 ? Array.from(vendors) : null
      },
      listMembers: {
        enumerable: true,
        value: Array.from(listMembers.entries()).map(([k, v]) => `${k}=${v}`)
      },
      nrTraceStateValue: {
        enumerable: true,
        value: nrTraceStateValue
      },
      nrTrustKey: {
        enumerable: true,
        value: trustedKey
      },
      intrinsics: {
        enumerable: true,
        value: intrinsics
      }
    })
  }
@param {object} params Parameters for construction.
@param {Agent} params.agent A New Relic agent instance.
@param {string[]} params.kvPairs The list of list members to parse, e.g.
`['a=b', 'c=d']`.
@param {object} [params.logger] A logger instance.

@throws {Error} If the provided agent is not a valid instance or any
list member is in an invalid format.