Fix Track.lookAt crash and fetchBuffer hang; bump to 2.0.1
- Track.lookAt: was calling client.user.lookAtEntity (undefined), now correctly routes to client.behavior.lookAtEntity — fixes unhandled promise rejections on every face-detection event - connection: httpGet/httpGetStream had no socket timeout; added 15 s req.setTimeout so fetchBuffer/pipe reject instead of hanging forever - connection: _txSend silently dropped commands when session not yet ready and returned a dead txId, causing callers to hang for the full timeout; now throws immediately with code NOT_READY Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2
API.md
2
API.md
@@ -1,6 +1,6 @@
|
|||||||
# rom-control
|
# rom-control
|
||||||
|
|
||||||
Discord.js-style OOP client for the Jibo ROM WebSocket API (port 8160).
|
Robust client for the Jibo ROM WebSocket API (port 8160).
|
||||||
|
|
||||||
**Requires:** Node.js ≥ 16, `ws` ^8.14.2
|
**Requires:** Node.js ≥ 16, `ws` ^8.14.2
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "rom-control",
|
"name": "rom-control",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"description": "Discord.js-style OOP client for the Jibo ROM WebSocket API",
|
"description": "Discord.js-style OOP client for the Jibo ROM WebSocket API",
|
||||||
"main": "./index.js",
|
"main": "./index.js",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -41,24 +41,30 @@ function httpPost(host, port, path, body) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function httpGet(host, port, path) {
|
function httpGet(host, port, path, timeoutMs = 15000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
const req = http.get({ host, port, path }, (res) => {
|
const req = http.get({ host, port, path }, (res) => {
|
||||||
res.on('data', d => chunks.push(d));
|
res.on('data', d => chunks.push(d));
|
||||||
res.on('end', () => resolve(Buffer.concat(chunks)));
|
res.on('end', () => resolve(Buffer.concat(chunks)));
|
||||||
});
|
});
|
||||||
|
req.setTimeout(timeoutMs, () => {
|
||||||
|
req.destroy(Object.assign(new Error('fetchMedia timed out'), { code: 'FETCH_TIMEOUT' }));
|
||||||
|
});
|
||||||
req.on('error', reject);
|
req.on('error', reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function httpGetStream(host, port, path, dest) {
|
function httpGetStream(host, port, path, dest, timeoutMs = 15000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const req = http.get({ host, port, path }, (res) => {
|
const req = http.get({ host, port, path }, (res) => {
|
||||||
res.pipe(dest);
|
res.pipe(dest);
|
||||||
res.on('end', resolve);
|
res.on('end', resolve);
|
||||||
dest.on('close', () => req.destroy());
|
dest.on('close', () => req.destroy());
|
||||||
});
|
});
|
||||||
|
req.setTimeout(timeoutMs, () => {
|
||||||
|
req.destroy(Object.assign(new Error('fetchMediaStream timed out'), { code: 'FETCH_TIMEOUT' }));
|
||||||
|
});
|
||||||
req.on('error', reject);
|
req.on('error', reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -323,7 +329,9 @@ class RomConnection extends EventEmitter {
|
|||||||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||||
// Don't send any command except StartSession before the session ID arrives.
|
// Don't send any command except StartSession before the session ID arrives.
|
||||||
// Commands sent with an empty SessionID are rejected by ROM with 403 Forbidden.
|
// Commands sent with an empty SessionID are rejected by ROM with 403 Forbidden.
|
||||||
if (!this.sessionID && command.Type !== 'StartSession') return txId;
|
if (!this.sessionID && command.Type !== 'StartSession') {
|
||||||
|
throw Object.assign(new Error(`Cannot send ${command.Type}: session not ready`), { code: 'NOT_READY' });
|
||||||
|
}
|
||||||
|
|
||||||
this._txCommands.set(txId, command.Type);
|
this._txCommands.set(txId, command.Type);
|
||||||
if (this._txCommands.size > 60) {
|
if (this._txCommands.size > 60) {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Track {
|
|||||||
|
|
||||||
// Look at this entity. Resolves when the head reaches the target.
|
// Look at this entity. Resolves when the head reaches the target.
|
||||||
async lookAt(track = true) {
|
async lookAt(track = true) {
|
||||||
return this._client.user.lookAtEntity(this.id, track);
|
return this._client.behavior.lookAtEntity(this.id, track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user