```import livekit.proto.RoomConfiguration; import ...
# ask-ai
r
Copy code
import livekit.proto.RoomConfiguration;
import livekit.proto.RoomAgentDispatch;
Cannot resolve symbol 'proto' In Java. using <io.livekit.version>0.10.1</io.livekit.version>
Copy code
<dependency>
    <groupId>io.livekit</groupId>
    <artifactId>livekit-server</artifactId>
    <version>${io.livekit.version}</version>
</dependency>
t
Thanks for reaching out, Gaurav. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
You're seeing "Cannot resolve symbol 'proto'" because the Protocol Buffer classes (like
RoomConfiguration
and
RoomAgentDispatch
) are not included in the
livekit-server
artifact. Add the
livekit-protocol
dependency so those generated classes are available. Add this to your pom.xml (using your same version variable):
Copy code
<dependency>
  <groupId>io.livekit</groupId>
  <artifactId>livekit-protocol</artifactId>
  <version>${io.livekit.version}</version>
</dependency>
After that the imports should resolve:
Copy code
import livekit.proto.RoomConfiguration;
import livekit.proto.RoomAgentDispatch;
If you still see the error after adding the dependency, tell me: • your full pom.xml (or relevant dependency section), and • your IDE (IntelliJ/VS Code) so I can suggest IDE-specific refresh steps. Sources: Server-side | livekit/livekit_composite | DeepWiki
r
[INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 15.183 s [INFO] Finished at: 2025-12-16T134552+05:30 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal on project jchat-manager: Could not resolve dependencies for project com.oneassistjchat managerjar:0.0.1-SNAPSHOT [ERROR] dependency: io.livekitlivekit protocoljar:0.10.1 (compile) [ERROR] Could not find artifact io.livekitlivekit protocoljar:0.10.1 in spring-milestones (https://repo.spring.io/milestone) [ERROR] Could not find artifact io.livekitlivekit protocoljar:0.10.1 in AsposeJavaAPI (https://releases.aspose.com/java/repo/) [ERROR] Could not find artifact io.livekitlivekit protocoljar:0.10.1 in central (https://repo.maven.apache.org/maven2) [ERROR]
t
Thanks — you're hitting this because Maven can't find
io.livekit:livekit-protocol:0.10.1
. That artifact/version is not published to the public Maven repositories you have configured, which is why the build fails. What you can do next: • Remove the
livekit-protocol
dependency and use the official Java server SDK instead (look up
io.livekit:server-sdk-java
versions on Maven Central) if your work can be done through the server SDK APIs. • If you need the protobuf classes (
livekit.proto.*
), clone the LiveKit protocol repo and generate Java classes locally with
protoc
, then include the generated sources or a local JAR in your build. Repository: github.com/livekit/protocol • Optionally add JitPack to your repositories if you plan to build a published artifact from the repo:
Copy code
<repository>
    <id><http://jitpack.io|jitpack.io></id>
    <url><https://jitpack.io></url>
  </repository>
If you want, paste your pom.xml (dependencies + repositories) and tell me whether you need runtime server APIs or the raw proto classes — I’ll give exact pom snippets and the simplest path forward. Sources: Rust SDKs | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki | SDKs | livekit/livekit_composite | DeepWiki | Android quickstart | LiveKit docs | Android quickstart (Jetpack Compose) | LiveKit docs
r
Copy code
package com.oneassist.jcm.proxy.livekit;

import com.oneassist.jcm.api.dto.response.VoiceAccessTokenResponseDto;
import io.livekit.server.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;

import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * Spring Boot Application and REST Controller for generating LiveKit Tokens.
 * To run:
 * 1. Ensure the required Maven dependencies (livekit-server-sdk, spring-boot-starter-web) are included.
 * 2. Set environment variables: LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET.
 * 3. Run the main method: mvn spring-boot:run
 */
@Component
@Slf4j
public class LivekitProxy {

    @Value("${livekit_api_key}")
    private String apiKey;

    @Value("${livekit_api_secret}")
    private String apiSecret;

    @Value("${livekit_url}")
    private String livekitUrl;

    private static final Set<String> VALID_LANGUAGES = Set.of(
            "hi-IN", "en-IN", "bn-IN", "gu-IN", "kn-IN", "ml-IN", "mr-IN", "or-IN", "pa-IN", "ta-IN", "te-IN"
    );

    private static final String DEFAULT_LANGUAGE = "hi-IN";
    private static final String DEFAULT_VOICE = "anushka";

    private final SecureRandom random = new SecureRandom();


    public VoiceAccessTokenResponseDto generateLivekitToken(Integer chatId, String name) {

        try {
            final String language =DEFAULT_LANGUAGE;
            final String voice = DEFAULT_VOICE;

            String roomBase = "conversation-ai-" + generateRandomHex(8);

            boolean hasSuffix = false;
            for (String lang : VALID_LANGUAGES) {
                if (roomBase.contains("-" + lang) || roomBase.endsWith("-" + lang)) {
                    hasSuffix = true;
                    break;
                }
            }

            String roomName;
            if (!hasSuffix) {
                if (chatId != null && chatId!=0) {
                    roomName = String.format("%s-%s-%s-%s", roomBase, chatId, language, voice);
                } else {
                    roomName = String.format("%s-%s-%s", roomBase, language, voice);
                }
            } else {
                roomName = roomBase;
            }

            String participantName = name != null && !name.isEmpty()
                    ? name
                    : "user-" + generateRandomHex(4);

            <http://log.info|log.info>("Generating token for participant: {} in room: {} (language: {}, voice: {}, chat_id: {})", participantName, roomName, language, voice, chatId);

            AccessToken token = new AccessToken(apiKey, apiSecret);
            token.setTtl(600);
            token.setIdentity(participantName);
            token.setName(participantName);

            token.addGrants(
                new RoomJoin(true),
                new Room(roomName),
                new CanPublish(true),
                new CanSubscribe(true),
                new CanPublishData(true)
            );

            // Dispatch agent explicitly using LiveKit API
            // The agent is registered with agent_name="voice-assistant" in agent.py
            // We dispatch the agent to the room asynchronously after token generation
            dispatchAgentToRoom(roomName, language, voice, chatId, participantName);

            String jwt = token.toJwt();

            // 5. Prepare response (convert URL to wss/https if needed)
            String safeUrl = livekitUrl.replace("ws://", "wss://").replace("http://", "https://");

            VoiceAccessTokenResponseDto responseDto = VoiceAccessTokenResponseDto.builder().authToken(jwt).wssUrl(safeUrl).roomName(roomName).language(language).voice(voice).build();

            if (chatId != null && chatId!=0) {
                responseDto.setChatId(chatId);
            }

            <http://log.info|log.info>("Token generated successfully for room: {}", roomName);
            return responseDto;

        } catch (Exception e) {
            log.error("Exception while generating token," , e);
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to generate token: " + e.getMessage());
        }
    }

    private String generateRandomHex(int length) {
        byte[] bytes = new byte[length];
        random.nextBytes(bytes);
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * Dispatch the voice-assistant agent to the specified room using LiveKit API
     * This is called asynchronously to avoid blocking token generation
     */
    private void dispatchAgentToRoom(String roomName, String language, String voice, Integer chatId, String participantName) {
        CompletableFuture.runAsync(() -> {
            try {
                // Build metadata JSON
                Map<String, String> metadataMap = new HashMap<>();
                metadataMap.put("language", language);
                metadataMap.put("voice", voice);
                if (chatId != null && chatId != 0) {
                    metadataMap.put("chat_id", String.valueOf(chatId));
                }
                metadataMap.put("user_id", participantName);
                
                StringBuilder metadataJson = new StringBuilder("{");
                boolean first = true;
                for (Map.Entry<String, String> entry : metadataMap.entrySet()) {
                    if (!first) metadataJson.append(",");
                    metadataJson.append("\"").append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\"");
                    first = false;
                }
                metadataJson.append("}");
                
                // Use LiveKit API client to dispatch agent
                // Note: This requires the LiveKit API client to be available
                // If AgentDispatchService is not available in your SDK version,
                // the agent will use automatic dispatch based on room patterns
                try {
                    LiveKitAPI api = new LiveKitAPI(livekitUrl, apiKey, apiSecret);
                    // Note: AgentDispatchService API may vary by SDK version
                    // If not available, agent will be dispatched automatically when participant joins
                    <http://log.info|log.info>("Agent 'voice-assistant' will be dispatched to room: {} (metadata: {})", roomName, metadataJson.toString());
                    // Uncomment when AgentDispatchService is available:
                    // api.getAgentDispatchService().createDispatch(roomName, "voice-assistant", metadataJson.toString());
                } catch (Exception e) {
                    log.debug("AgentDispatchService not available. Agent will use automatic dispatch: {}", e.getMessage());
                }
            } catch (Exception e) {
                log.warn("Failed to dispatch agent explicitly. Agent will use automatic dispatch: {}", e.getMessage());
            }
        });
    }
}
t
You're close — two actionable points to fix your build and agent-dispatch flow. 1) Fix the build / missing imports • The artifact
io.livekit:livekit-protocol:0.10.1
is not published to public Maven repos, so Maven can't resolve it. Do not add that dependency. • Use the LiveKit server SDK for JVM instead (the JVM-friendly package is the server SDK / server-sdk-kotlin). Add the server SDK dependency that is published to Maven Central or the correct group/artifact your project uses. Example (replace with the actual published version you choose):
Copy code
<dependency>
  <groupId>io.livekit</groupId>
  <artifactId>server-sdk-java</artifactId>
  <version>REPLACE_WITH_PUBLISHED_VERSION</version>
</dependency>
OR use the Kotlin JVM SDK:
Copy code
<dependency>
  <groupId>io.livekit</groupId>
  <artifactId>server-sdk-kotlin</artifactId>
  <version>REPLACE_WITH_PUBLISHED_VERSION</version>
</dependency>
2) How to get the protobuf classes (RoomConfiguration / RoomAgentDispatch) • If you need
livekit.proto.*
classes directly, generate them locally from the LiveKit proto repository and include the generated Java sources or a local JAR in your project: ◦ Clone: github.com/livekit/protocol ◦ Run
protoc
(Java plugin) to generate Java classes from the .proto files ◦ Add generated sources to your module or install a local JAR to your Maven repo • Alternatively, you can embed room-agent dispatch in the AccessToken (preferred if you only need automatic agent dispatch). The server SDK supports adding room configuration to the token using
RoomConfiguration
and
RoomAgentDispatch
so the agent will be dispatched automatically when the room is created/joined. That avoids needing the standalone protocol artifact. Agent dispatch in your code • Your current pattern (building metadata JSON and attempting to call an AgentDispatchService) is fine if a client API exists in your SDK version. However: ◦ If AgentDispatchService is not available in your SDK, remove or keep that code commented and rely on token-based dispatch via `RoomConfiguration`/`RoomAgentDispatch` in the token before returning it. ◦ Example approach: set `token`'s room configuration to include a
RoomAgentDispatch
entry for agent_name "voice-assistant" with the metadata JSON you already build. Next steps I can help with • If you paste your pom.xml I will give exact dependency and repository entries to fix the build. • If you want, I can provide the minimal
protoc
commands and pom plugin snippet to generate Java classes from the protocol repo. Which would you prefer: use token-based
RoomConfiguration
(simpler) or generate/import the proto classes? Sources: server-sdk-kotlin | livekit/livekit_composite | DeepWiki