Discussions
Connection error with sdk
I'm unable to connect, and I'm always getting a 401 error. When I use any other API or directly interact with other AIs, everything works fine. However, when I use the D-ID SDK, it throws a 401 error. I even tried running your demo project, but it doesn't work there either. I think there might be an issue with the authorization value I'm sending.
this is the code
// CSS import
import "./style.css";
// 1. Import the Agents SDK library
import * as sdk from "@d-id/client-sdk";
// 2. Paste the `data-agent-id' in the 'agentId' variable
let agentId = "agt_y0HoXmlz";
// 3. Paste the 'data-client-key' in the 'auth.clientKey' variable
let auth = {
type: "key",
clientKey: "aGFtemFhc2hAemFsdGVjaC5haQ:VnC8270Cy83fzjrBXEH5T",
};
// HTML Variables declaration
let videoElement = document.querySelector("#videoElement");
let textArea = document.querySelector("#textArea");
let langSelect = document.querySelector("#langSelect");
let speechButton = document.querySelector("#speechButton");
let answers = document.querySelector("#answers");
let connectionLabel = document.querySelector("#connectionLabel");
let chatButton = document.querySelector("#chatButton");
let speakButton = document.querySelector("#speakButton");
let reconnectButton = document.querySelector("#reconnectButton");
let srcObject;
// 4. Define the SDK callbacks functions in this object
const callbacks = {
// Link the HTML Video element with the WebRTC Stream Object (Video & Audio tracks)
onSrcObjectReady(value) {
console.log("onSrcObjectReady():", value);
videoElement.srcObject = value;
srcObject = value;
return srcObject;
},
// Connection States callback method
onConnectionStateChange(state) {
console.log("onConnectionStateChange(): ", state);
if (state == "connecting") {
connectionLabel.innerHTML = "Connecting..";
document.querySelector("#container").style.display = "flex";
document.querySelector("#hidden").style.display = "none";
} else if (state == "connected") {
// Setting the 'Enter' Key to Send a message
textArea.addEventListener("keypress", (event) => {
if (event.key === "Enter") {
event.preventDefault();
chat();
}
});
chatButton.removeAttribute("disabled");
speakButton.removeAttribute("disabled");
langSelect.removeAttribute("disabled");
speechButton.removeAttribute("disabled");
connectionLabel.innerHTML = "Online";
} else if (state == "disconnected" || state == "closed") {
textArea.removeEventListener("keypress", (event) => {
if (event.key === "Enter") {
event.preventDefault();
chat();
}
});
document.querySelector(
"#hidden_h2"
).innerHTML = `${agentManager.agent.preview_name} Disconnected`;
document.querySelector("#hidden").style.display = "block";
document.querySelector("#container").style.display = "none";
chatButton.setAttribute("disabled", true);
speakButton.setAttribute("disabled", true);
langSelect.setAttribute("disabled", true);
speechButton.setAttribute("disabled", true);
connectionLabel.innerHTML = "";
}
},
// Switching between the idle and streamed videos
onVideoStateChange(state) {
console.log("onVideoStateChange(): ", state);
if (state == "STOP") {
videoElement.muted = true;
videoElement.srcObject = undefined;
videoElement.src = agentManager.agent.presenter.idle_video;
} else {
videoElement.muted = false;
videoElement.src = "";
videoElement.srcObject = srcObject;
connectionLabel.innerHTML = "Online";
}
},
// New messages callback method
onNewMessage(messages, type) {
console.log("onNewMessage():", messages, type);
// We want to show only the last message from the entire 'messages' array
let lastIndex = messages.length - 1;
let msg = messages[lastIndex];
// Show Rating buttons only for the Agent's (assistant) full answers
if (msg.role == "assistant" && messages.length != 1) {
if (type == "answer") {
answers.innerHTML += `${timeDisplay()} - [${msg.role}] : ${
msg.content
} <button id='${
msg.id
}_plus' title='agentManager.rate() -> Rate this answer (+)'>+</button> <button id='${
msg.id
}_minus' title='agentManager.rate() -> Rate this answer (-)'>-</button> <br>`;
document
.getElementById(`${msg.id}_plus`)
.addEventListener("click", () => rate(msg.id, 1));
document
.getElementById(`${msg.id}_minus`)
.addEventListener("click", () => rate(msg.id, -1));
}
} else {
answers.innerHTML += `${timeDisplay()} - [${msg.role}] : ${
msg.content
} <br>`;
}
// Auto-scroll to the last message
answers.scrollTop = answers.scrollHeight;
},
// Error handling
onError(error, errorData) {
connectionLabel.innerHTML = <span style="color:red">Something went wrong :(</span>
;
console.log("Error:", error, "Error Data", errorData);
},
};
// 5. Define the Stream options object (Optional)
let streamOptions = { compatibilityMode: "auto", streamWarmup: true };
// Local functions to utilize the Agent's SDK methods:
// agentManager.speak() -> Streaming API (Bring your own LLM)
function speak() {
let val = textArea.value;
// Speak supports a minimum of 3 characters
if (val !== "" && val.length > 2) {
let speak = agentManager.speak({
type: "text",
input: val,
});
console.log(agentManager.speak("${val}")
);
connectionLabel.innerHTML = "Streaming..";
}
}
// agentManager.chat() -> Agents API (communicating with your created Agent and its knowledge -> Streams back the D-ID's LLM response)
function chat() {
let val = textArea.value;
if (val !== "") {
let chat = agentManager.chat(val);
console.log("agentManager.chat()");
connectionLabel.innerHTML = "Thinking..";
textArea.value = "";
}
}
// agentManager.rate() -> Rating the Agent's answers - for future Agents Analytics and Insights feature
function rate(messageID, score) {
let rate = agentManager.rate(messageID, score);
console.log(Message ID: ${messageID} Rated:${score}\n
, "Result", rate);
}
// agentManager.reconnect() -> Reconnect the Agent to a new WebRTC session
function reconnect() {
console.log("clicked");
let reconnect = agentManager.reconnect();
console.log("agentManager.reconnect()", reconnect);
}
// agentManager.disconnect() -> Terminates the current Agent's WebRTC session (Not implemneted in this code example)
function disconnect() {
let disconnect = agentManager.disconnect();
console.log("agentManager.disconnect()", disconnect);
}
// JS Utility Functions:
// 'cleaner' time display in (HH:MM:SS)
function timeDisplay() {
const currentTime = new Date();
const hours = currentTime.getHours().toString().padStart(2, "0");
const minutes = currentTime.getMinutes().toString().padStart(2, "0");
const seconds = currentTime.getSeconds().toString().padStart(2, "0");
const formattedTime = ${hours}:${minutes}:${seconds}
;
return formattedTime;
}
// Reminder to place Agent ID and Client Key at the top of this file
if (agentId == "" || auth.clientKey == "") {
connectionLabel.innerHTML = <span style='color:red; font-weight:bold'> Missing agentID and auth.clientKey variables</span>
;
console.error("Missing agentID and auth.clientKey variables");
console.log(
Missing agentID and auth.clientKey variables:\n\nFetch the data-client-key and the data-agent-id as explained on the Agents SDK Overview Page:\nhttps://docs.d-id.com/reference/agents-sdk-overview\n\nPaste these into their respective variables at the top of the main.js file and save.
);
}
// Event Listeners for Agent's built-in methods
chatButton.addEventListener("click", () => chat());
speakButton.addEventListener("click", () => speak());
reconnectButton.addEventListener("click", () => reconnect());
speechButton.addEventListener("click", () => toggleStartStop());
// Focus on input and button disabling when loading
window.addEventListener("load", () => {
textArea.focus(), chatButton.setAttribute("disabled", true);
speakButton.setAttribute("disabled", true);
langSelect.setAttribute("disabled", true);
speechButton.setAttribute("disabled", true);
});
// Finally
console.log("sdk.createAgentManager()", auth);
// 6. Create the 'agentManager' instance with the values created in previous steps
let agentManager = await sdk.createAgentManager(agentId, {
auth,
callbacks,
streamOptions,
});
// Displaying the Agent's name in the HTML Header
document.querySelector("#previewName").innerHTML =
agentManager.agent.preview_name;
// Setting the thumbnail as the video background image to avoid "flickering".
// Set one of the following (depends on the Avatar's type): agentManager.agent.presenter.source_url / agentManager.agent.presenter.thumbnail
document.querySelector(
"#videoElement"
).style.backgroundImage = url(${agentManager.agent.presenter.source_url})
;
// agentManager.connect() method -> Creating a new WebRTC session and connecting it to the Agent
console.log("agentManager.connect()");
agentManager.connect();
// Happy Coding!