ronantakizawa/codereview-bench huggingface dataset:
Repository: moeru-ai/airi
File: packages/stage-ui/src/components/Scenes/VRM.vue (Vue)

Code before:
//   if (camera.value) {
//     camera.value.aspect = width.value / height.value
//     camera.value.updateProjectionMatrix()
//   }
// })

watch(selectedModel, () => {
  if (camera.value) {
    camera.value.position.set(
      initialCameraPosition.value.x,
      initialCameraPosition.value.y,
      initialCameraPosition.value.z,
    )
    camera.value.updateProjectionMatrix()
  }
})

defineExpose({
  setExpression: (expression: string) => {
    modelRef.value?.setExpression(expression)
  },
})
</script>

<template>
  <div ref="VRMContainerRef" w="100%" h="100%">
    <TresCanvas v-if="camera" :camera="camera" :alpha="true" :antialias="true" :width="width" :height="height">
      <TresAxesHelper :size="1" />
      <TresDirectionalLight :color="0xFFFFFF" :intensity="1.2" :position="[1, 1, 1]" />
      <TresAmbientLight :color="0xFFFFFF" :intensity="1.5" />
      <VRMModel
        ref="modelRef"
        :key="selectedModel"
        :model="selectedModel"
        idle-animation="/assets/vrm/animations/idle_loop.vrma"
        :paused="false"
        @load-model-progress="(val) => emit('loadModelProgress', val)"
        @error="(val) => emit('error', val)"
      />
      <!-- <TresPerspectiveCamera :position="[initialCameraPosition.x, initialCameraPosition.y, initialCameraPosition.z]" :fov="cameraFOV"/> -->
      <OrbitControls />
    </TresCanvas>
  </div>
</template>


Review comment (suggestion):
```suggestion
  <div ref="vrmContainerRef" w="100%" h="100%">
```

Code after:
//   if (camera.value) {
//     camera.value.aspect = width.value / height.value
//     camera.value.updateProjectionMatrix()
//   }
// })

watch(selectedModel, () => {
  if (camera.value) {
    camera.value.position.set(
      initialCameraPosition.value.x,
      initialCameraPosition.value.y,
      initialCameraPosition.value.z,
    )
    camera.value.updateProjectionMatrix()
  }
})

defineExpose({
  setExpression: (expression: string) => {
    modelRef.value?.setExpression(expression)
  },
})
</script>

<template>
  <div ref="vrmContainerRef" w="100%" h="100%">
    <TresCanvas v-if="camera" :camera="camera" :alpha="true" :antialias="true" :width="width" :height="height">
      <TresAxesHelper :size="1" />
      <TresDirectionalLight :color="0xFFFFFF" :intensity="1.2" :position="[1, 1, 1]" />
      <TresAmbientLight :color="0xFFFFFF" :intensity="1.5" />
      <VRMModel
        ref="modelRef"
        :key="selectedModel"
        :model="selectedModel"
        idle-animation="/assets/vrm/animations/idle_loop.vrma"
        :paused="false"
        @load-model-progress="(val) => emit('loadModelProgress', val)"
        @error="(val) => emit('error', val)"
      />
      <!-- <TresPerspectiveCamera :position="[initialCameraPosition.x, initialCameraPosition.y, initialCameraPosition.z]" :fov="cameraFOV"/> -->
      <OrbitControls />
    </TresCanvas>
  </div>
</template>
Repository: moeru-ai/airi
File: packages/stage-ui/src/stores/vrm.ts (TypeScript)

Code before:
import { useLocalStorage } from '@vueuse/core'
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'

export const useVRM = defineStore('vrm', () => {
  const modelFile = ref<File>()

  const defaultModelUrl = '/assets/vrm/models/AvatarSample-B/AvatarSample_B.vrm'
  const modelUrl = useLocalStorage('settings/vrm/modelURL', '')

  const loadSource = ref<'file' | 'url'>('url')
  const loadingModel = ref(false)

  const scale = useLocalStorage('settings/live2d/cameraScale', 1)
  const modelSize = useLocalStorage('settings/vrm/modelSize', { x: 0, y: 0, z: 0 })
  const modelOrigin = useLocalStorage('settings/vrm/modelOrigin', { x: 0, y: 0, z: 0 })
  const modelOffset = useLocalStorage('settings/vrm/modelOffset', { x: 0, y: 0, z: 0 })

  const position = computed(() => ({
    x: modelOrigin.value.x + modelOffset.value.x,
    y: modelOrigin.value.y + modelOffset.value.y,
    z: modelOrigin.value.z + modelOffset.value.z,
  }))
  const positionInPercentageString = computed(() => ({
    x: `${position.value.x}%`,
    y: `${position.value.y}%`,
    z: `${position.value.z}%`,
  }))
  const cameraFOV = useLocalStorage('settings/vrm/cameraFOV', 40)
  const initialCameraPosition = useLocalStorage('settings/vrm/initialCameraPosition', { x: 0, y: 0, z: -1 })

  const modelObjectUrl = ref<string>()
  const modelRotationY = useLocalStorage('settings/vrm/modelRotationY', 0)


Review comment (suggestion):
```suggestion
  const modelUrl = useLocalStorage('settings/vrm/modelURL', defaultModelUrl)
```

Code after:
import { useLocalStorage } from '@vueuse/core'
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'

export const useVRM = defineStore('vrm', () => {
  const modelFile = ref<File>()

  const defaultModelUrl = '/assets/vrm/models/AvatarSample-B/AvatarSample_B.vrm'
  const modelUrl = useLocalStorage('settings/vrm/modelURL', defaultModelUrl)

  const loadSource = ref<'file' | 'url'>('url')
  const loadingModel = ref(false)

  const scale = useLocalStorage('settings/live2d/cameraScale', 1)
  const modelSize = useLocalStorage('settings/vrm/modelSize', { x: 0, y: 0, z: 0 })
  const modelOrigin = useLocalStorage('settings/vrm/modelOrigin', { x: 0, y: 0, z: 0 })
  const modelOffset = useLocalStorage('settings/vrm/modelOffset', { x: 0, y: 0, z: 0 })

  const position = computed(() => ({
    x: modelOrigin.value.x + modelOffset.value.x,
    y: modelOrigin.value.y + modelOffset.value.y,
    z: modelOrigin.value.z + modelOffset.value.z,
  }))
  const positionInPercentageString = computed(() => ({
    x: `${position.value.x}%`,
    y: `${position.value.y}%`,
    z: `${position.value.z}%`,
  }))
  const cameraFOV = useLocalStorage('settings/vrm/cameraFOV', 40)
  const initialCameraPosition = useLocalStorage('settings/vrm/initialCameraPosition', { x: 0, y: 0, z: -1 })

  const modelObjectUrl = ref<string>()
  const modelRotationY = useLocalStorage('settings/vrm/modelRotationY', 0)
Repository: moeru-ai/airi
File: packages/stage-ui/src/components/Scenes/VRM.vue (Vue)

Code before:
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { useElementBounding } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { onMounted, ref, shallowRef, watch } from 'vue'

import * as THREE from 'three'

import { useVRM } from '../../stores'
import { OrbitControls, VRMModel } from '../Scenes'

const emit = defineEmits<{
  (e: 'loadModelProgress', value: number): void
  (e: 'error', value: unknown): void
}>()
const VRMContainerRef = ref<HTMLDivElement>()
const { width, height } = useElementBounding(VRMContainerRef)
const {
  selectedModel,
  cameraFOV,
  initialCameraPosition,
} = storeToRefs(useVRM())

const modelRef = ref<InstanceType<typeof VRMModel>>()

const camera = shallowRef(new THREE.PerspectiveCamera())

onMounted(() => {
  if (VRMContainerRef.value) {
    camera.value.aspect = width.value / height.value
    camera.value.fov = cameraFOV.value
    camera.value.position.set(
      initialCameraPosition.value.x,
      initialCameraPosition.value.y,
      initialCameraPosition.value.z,
    )
    camera.value.updateProjectionMatrix()
  }
})

watch(cameraFOV, (newFov) => {
  if (camera.value) {

Review comment (suggestion):
```suggestion
const { width, height } = useElementBounding(vrmContainerRef)
```

Code after:
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { useElementBounding } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { onMounted, ref, shallowRef, watch } from 'vue'

import * as THREE from 'three'

import { useVRM } from '../../stores'
import { OrbitControls, VRMModel } from '../Scenes'

const emit = defineEmits<{
  (e: 'loadModelProgress', value: number): void
  (e: 'error', value: unknown): void
}>()
const vrmContainerRef = ref<HTMLDivElement>()
const { width, height } = useElementBounding(vrmContainerRef)
const {
  selectedModel,
  cameraFOV,
  initialCameraPosition,
} = storeToRefs(useVRM())

const modelRef = ref<InstanceType<typeof VRMModel>>()

const camera = shallowRef(new THREE.PerspectiveCamera())

onMounted(() => {
  if (vrmContainerRef.value) {
    camera.value.aspect = width.value / height.value
    camera.value.fov = cameraFOV.value
    camera.value.position.set(
      initialCameraPosition.value.x,
      initialCameraPosition.value.y,
      initialCameraPosition.value.z,
    )
    camera.value.updateProjectionMatrix()
  }
})

watch(cameraFOV, (newFov) => {
  if (camera.value) {
Repository: moeru-ai/airi
File: packages/stage-ui/src/utils/tts.ts (TypeScript)

Code before:
      }

      chunk += buffer + value
      chunkWordsCount += words.length
      buffer = ''

      if (flush || hard || chunkWordsCount > maximumWords || yieldCount < boost) {
        const text = chunk.trim()
        yield {
          text,
          words: chunkWordsCount,
          reason: flush ? 'flush' : hard ? 'hard' : chunkWordsCount > maximumWords ? 'limit' : 'boost',
        }
        yieldCount++
        chunk = ''
        chunkWordsCount = 0
      }

      previousValue = value
      current = await iterator.next()
      continue
    }

    buffer += value
    // eslint-disable-next-line no-console
    console.debug('current buffer: ', buffer)
    previousValue = value
    // For debugging why it stuck at "xxxx\u200B"
    const next = await iterator.next()
    // if (next.value ==='\u200B') {
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}

export async function chunkToTTSQueue(reader: ReaderLike, queue: UseQueueReturn<string>) {
  try {

Review comment (suggestion):
```suggestion
    // TODO: remove later
    // eslint-disable-next-line no-console
```

Code after:
      }

      chunk += buffer + value
      chunkWordsCount += words.length
      buffer = ''

      if (flush || hard || chunkWordsCount > maximumWords || yieldCount < boost) {
        const text = chunk.trim()
        yield {
          text,
          words: chunkWordsCount,
          reason: flush ? 'flush' : hard ? 'hard' : chunkWordsCount > maximumWords ? 'limit' : 'boost',
        }
        yieldCount++
        chunk = ''
        chunkWordsCount = 0
      }

      previousValue = value
      current = await iterator.next()
      continue
    }

    buffer += value
    // TODO: remove later
    // eslint-disable-next-line no-console
    console.debug('current buffer: ', buffer)
    previousValue = value
    // For debugging why it stuck at "xxxx\u200B"
    const next = await iterator.next()
    // if (next.value ==='\u200B') {
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // TODO: remove later
  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}
Repository: moeru-ai/airi
File: packages/stage-ui/src/utils/tts.ts (TypeScript)

Code before:
        chunk = ''
        chunkWordsCount = 0
      }

      previousValue = value
      current = await iterator.next()
      continue
    }

    buffer += value
    // eslint-disable-next-line no-console
    console.debug('current buffer: ', buffer)
    previousValue = value
    // For debugging why it stuck at "xxxx\u200B"
    const next = await iterator.next()
    // if (next.value ==='\u200B') {
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}

export async function chunkToTTSQueue(reader: ReaderLike, queue: UseQueueReturn<string>) {
  try {
    for await (const chunk of chunkTTSInput(reader)) {
      // eslint-disable-next-line no-console
      console.debug('chunk to be pushed: ', chunk)
      await queue.add(chunk.text)
    }
  }
  catch (e) {
    console.error('Error chunking stream to TTS queue:', e)
  }
}


Review comment (suggestion):
```suggestion
  // TODO: remove later
  // eslint-disable-next-line no-console
```

Code after:
        chunk = ''
        chunkWordsCount = 0
      }

      previousValue = value
      current = await iterator.next()
      continue
    }

    buffer += value
    // TODO: remove later
    // eslint-disable-next-line no-console
    console.debug('current buffer: ', buffer)
    previousValue = value
    // For debugging why it stuck at "xxxx\u200B"
    const next = await iterator.next()
    // if (next.value ==='\u200B') {
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // TODO: remove later
  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}

export async function chunkToTTSQueue(reader: ReaderLike, queue: UseQueueReturn<string>) {
  try {
    for await (const chunk of chunkTTSInput(reader)) {
      // TODO: remove later
      // eslint-disable-next-line no-console
      console.debug('chunk to be pushed: ', chunk)
      await queue.add(chunk.text)
    }
  }
  catch (e) {
    console.error('Error chunking stream to TTS queue:', e)
  }
}
Repository: moeru-ai/airi
File: packages/stage-ui/src/utils/tts.ts (TypeScript)

Code before:
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}

export async function chunkToTTSQueue(reader: ReaderLike, queue: UseQueueReturn<string>) {
  try {
    for await (const chunk of chunkTTSInput(reader)) {
      // eslint-disable-next-line no-console
      console.debug('chunk to be pushed: ', chunk)
      await queue.add(chunk.text)
    }
  }
  catch (e) {
    console.error('Error chunking stream to TTS queue:', e)
  }
}


Review comment (suggestion):
```suggestion
      // TODO: remove later
      // eslint-disable-next-line no-console
```

Code after:
    // if (next.value ==='\u200B') {
    //   console.debug("TTS_FLUSH get for the next value!")
    // } else {
    //   console.debug("the next value: ", next.value)
    // }
    current = next
  }

  // TODO: remove later
  // eslint-disable-next-line no-console
  console.debug('while loop ends, chunk/buffer:', chunk, buffer)
  if (chunk.length > 0 || buffer.length > 0) {
    const text = (chunk + buffer).trim()
    yield {
      text,
      words: chunkWordsCount + [...segmenter.segment(buffer)].filter(w => w.isWordLike).length,
      reason: 'flush',
    }
  }
}

export async function chunkToTTSQueue(reader: ReaderLike, queue: UseQueueReturn<string>) {
  try {
    for await (const chunk of chunkTTSInput(reader)) {
      // TODO: remove later
      // eslint-disable-next-line no-console
      console.debug('chunk to be pushed: ', chunk)
      await queue.add(chunk.text)
    }
  }
  catch (e) {
    console.error('Error chunking stream to TTS queue:', e)
  }
}
Repository: moeru-ai/airi
File: apps/stage-web/src/pages/settings/providers/index-tts-vllm.vue (Vue)

Code before:

  // Get model from configuration or use default
  const model = providerConfig.model as string | undefined || defaultModel

  // Index TTS doesn't need SSML conversion, but if SSML is provided, use it directly
  return await speechStore.speech(
    provider,
    model,
    input,
    voiceId,
    {
      ...providerConfig,
    },
  )
}

onMounted(async () => {
  const providerConfig = providersStore.getProviderConfig(providerId)
  const providerMetadata = providersStore.getProviderMetadata(providerId)
  if (await providerMetadata.validators.validateProviderConfig(providerConfig)) {
    await speechStore.loadVoicesForProvider(providerId)
  }
  else {
    console.error('Failed to validate provider config', providerConfig)
  }
})

watch(speedRatio, async () => {
  const providerConfig = providersStore.getProviderConfig(providerId)
  if (!providerConfig.audio) {
    providerConfig.audio = {}
  }

  (providerConfig.audio as any).speedRatio = speedRatio.value
})

watch([providers], async () => {
  const providerConfig = providersStore.getProviderConfig(providerId)
  const providerMetadata = providersStore.getProviderMetadata(providerId)
  if (await providerMetadata.validators.validateProviderConfig(providerConfig)) {
    await speechStore.loadVoicesForProvider(providerId)
  }
  else {
    console.error('Failed to validate provider config', providerConfig)
  }
}, {
  immediate: true,
})
</script>

<template>

Review comment (refactor):
```suggestion
```

True, let's remove this part, perhaps for other providers, this part can be removed safely, feel free to open PRs for that.

Code after:
  const model = providerConfig.model as string | undefined || defaultModel

  // Index TTS doesn't need SSML conversion, but if SSML is provided, use it directly
  return await speechStore.speech(
    provider,
    model,
    input,
    voiceId,
    {
      ...providerConfig,
    },
  )
}

watch([providers], async () => {
  const providerConfig = providersStore.getProviderConfig(providerId)
  const providerMetadata = providersStore.getProviderMetadata(providerId)
  if (await providerMetadata.validators.validateProviderConfig(providerConfig)) {
    await speechStore.loadVoicesForProvider(providerId)
  }
  else {
    console.error('Failed to validate provider config', providerConfig)
  }
}, {
  immediate: true,
})
</script>

<template>
  <SpeechProviderSettings
    :provider-id="providerId"
    :default-model="defaultModel"
  >
    <!-- Replace the default playground with our standalone component -->
    <template #playground>
      <SpeechPlayground
        :available-voices="availableVoices"
        :generate-speech="handleGenerateSpeech"
        :api-key-configured="apiKeyConfigured"
        default-text="Hello! This is a test of the Index TTS voice synthesis."
      />
    </template>
  </SpeechProviderSettings>
</template>

<route lang="yaml">
  meta:
    layout: settings
    stageTransition:
      name: slide
  </route>
Repository: moeru-ai/airi
File: packages/stage-ui/src/components/Scenes/VRM.vue (Vue)

Code before:
  if (!sceneReady.value || !modelRef.value)
    return
  if (newMode === 'camera') {
    lookAtCamera(cameraPosition.value)
  }
  else if (newMode === 'mouse') {
    lookAtMouse(mouseX.value, mouseY.value)
  }
  else {
    lookAtTarget.value = {
      x: 0,
      y: eyeHeight.value,
      z: -1000,
    }
  }
})

function canvasElement() {
  return tresCanvasRef.value?.renderer.value.domElement
}

defineExpose({
  setExpression: (expression: string) => {
    modelRef.value?.setExpression(expression)
  },
  canvasElement,
})
</script>

<template>
  <div ref="vrmContainerRef" w="100%" h="100%">
    <TresCanvas
      v-if="camera" v-show="sceneReady"
      :camera="camera"
      :antialias="true"
      :width="width"
      :height="height"
      :tone-mapping="ACESFilmicToneMapping"
      :tone-mapping-exposure="1"
      :preserve-drawing-buffer="true"
      @ready="onTresReady"
    >
      <OrbitControls ref="controlsRef" />
      <Environment
        v-if="envSelect === 'skyBox'"
        :sky-box-src="skyBoxSrc"
        :as-background="true"
      />
      <TresHemisphereLight
        v-else
        :color="formatHex(hemisphereSkyColor)"

Review comment (suggestion):
```suggestion
defineExpose({
  setExpression: (expression: string) => {
    modelRef.value?.setExpression(expression)
  },
  canvasElement: () => {
    return tresCanvasRef.value?.renderer.value.domElement
  },
```

Code after:
  if (!sceneReady.value || !modelRef.value)
    return
  if (newMode === 'camera') {
    lookAtCamera(cameraPosition.value)
  }
  else if (newMode === 'mouse') {
    lookAtMouse(mouseX.value, mouseY.value)
  }
  else {
    lookAtTarget.value = {
      x: 0,
      y: eyeHeight.value,
      z: -1000,
    }
  }
})

defineExpose({
  setExpression: (expression: string) => {
    modelRef.value?.setExpression(expression)
  },
  canvasElement: () => {
    return tresCanvasRef.value?.renderer.value.domElement
  },
})
</script>

<template>
  <div ref="vrmContainerRef" w="100%" h="100%">
    <TresCanvas
      v-if="camera" v-show="sceneReady"
      :camera="camera"
      :antialias="true"
      :width="width"
      :height="height"
      :tone-mapping="ACESFilmicToneMapping"
      :tone-mapping-exposure="1"
      :preserve-drawing-buffer="true"
      @ready="onTresReady"
    >
      <OrbitControls ref="controlsRef" />
      <Environment
        v-if="envSelect === 'skyBox'"
        :sky-box-src="skyBoxSrc"
        :as-background="true"
      />
      <TresHemisphereLight
        v-else
        :color="formatHex(hemisphereSkyColor)"
        :ground-color="formatHex(hemisphereGroundColor)"
        :position="[hemisphereLightPosition.x, hemisphereLightPosition.y, hemisphereLightPosition.z]"