Skip to content

[Web runtime] Add WebSocket action support (2/3) - #1593

Open
minggangw wants to merge 6 commits into
RobotWebTools:developfrom
minggangw:fix-1579-websocket
Open

[Web runtime] Add WebSocket action support (2/3)#1593
minggangw wants to merge 6 commits into
RobotWebTools:developfrom
minggangw:fix-1579-websocket

Conversation

@minggangw

@minggangw minggangw commented Sep 7, 2026

Copy link
Copy Markdown
Member

This PR adds ROS 2 action support to the rclnodejs/web WebSocket SDK and its type surface, enabling browser/runtime clients to send goals, receive feedback, await results, and request cancellation via the runtime’s action capability dispatch.

Changes:

  • Support typed goal submission through RosClient.action(), deliver feedback through onFeedback, and return an action handle after goal acceptance with a result promise and per-goal cancellation.
  • Expose read-only terminal status so callers can distinguish succeeded, canceled, aborted, and unknown outcomes without changing result payloads. Status remains undefined until a terminal response arrives.
  • Support cancellation requests through cancel(), resolving to undefined when accepted and propagating rejection errors to match the Promise<void> contract.
  • Accept null and undefined action options, reject invalid feedback callbacks before networking, and isolate exceptions thrown by valid callbacks so result delivery continues.
  • Reject actions during and after client closure, including clients whose lazy WebSocket has not opened. Clear pending action state on connection loss and avoid resubmitting goals after reconnection.
  • Map native numeric typed arrays to JSON number arrays and BigInt typed arrays to encoded string arrays in the public wire types.
  • Add runtime and TypeScript regression coverage for goal submission, feedback, cancellation, terminal status, connection lifecycle, invalid options, and typed goal validation.

Fix: #1579

Copilot AI lite review requested due to automatic review settings September 7, 2026 09:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new action() options handling can throw on null, and cancel() returns a payload despite being typed/documented as Promise<void>, so the implementation and declared API need to be aligned.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds ROS 2 action support to the rclnodejs/web WebSocket SDK and its type surface, enabling browser/runtime clients to send goals, receive feedback, await results, and request cancellation via the runtime’s action capability dispatch.

Changes:

  • Adds action-related TypeScript types (ActionName, wire-shape helpers, ActionHandle, ActionStatus) and a typed RosClient.action() overload in web/index.d.ts.
  • Implements WebSocket-side goal tracking/dispatch in web/client.js (goal map, feedback routing, terminal result handling, and cleanup on connection failure).
  • Adds new runtime+SDK integration tests for action dispatch and expands tsd coverage for the new types.
File summaries
File Description
web/index.d.ts Introduces action type helpers and the RosClient.action() API surface for the web SDK.
web/client.js Implements the WebSocket protocol handling for action goals, feedback, results, and cancellation.
test/types/index.test-d.ts Adds tsd assertions to validate the new ActionHandle/ActionStatus typings.
test/test-web-action.js Adds end-to-end tests covering action send_goal, feedback, result statuses, cancellation, and connection loss behavior.
Review details
  • Files reviewed: 3/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread web/client.js Outdated
Comment on lines +222 to +223
action(capability, payload, { onFeedback } = {}) {
if (this._closed || this._isUserClosed) {
Comment thread web/client.js
get status() {
return status;
},
cancel: () => this._cancelGoal(id),
@coveralls

coveralls commented Sep 7, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 90.904% (+0.1%) from 90.805% — minggangw:fix-1579-websocket into RobotWebTools:develop

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The cancellation return type mismatch and missing action-client type coverage must be addressed.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

web/client.js:276

  • _request() resolves with the cancel frame's payload, and the dispatcher includes the serialized CancelGoal response on success (lib/runtime/dispatcher.js:452-456). Consequently JavaScript callers receive an object even though ActionHandle.cancel() is declared as Promise<void>. Discard the internal response here (or change the public return type); the former preserves the newly documented API.
  _cancelGoal(goalId) {
    return this._request({ kind: 'action', op: 'cancel', goalId });
  • Files reviewed: 3/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +18 to +26
declare const webAction: ActionHandle<{ sequence: number[] }>;
expectType<Promise<{ sequence: number[] }>>(webAction.result);
expectType<ActionStatus | undefined>(webAction.status);
expectAssignable<ActionStatus>('succeeded');
expectAssignable<ActionStatus>('canceled');
expectAssignable<ActionStatus>('aborted');
expectAssignable<ActionStatus>('unknown');
expectError((webAction.status = 'succeeded'));
expectType<Promise<void>>(webAction.cancel());

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Validate feedback callbacks and prevent action() from reopening networking after client closure.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 3/4 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread web/client.js
if (this._isReconnecting) {
return Promise.reject(_connectionLostError());
}
const { onFeedback } = options ?? {};
Comment thread web/client.js
* @param {(feedback: *) => void} [options.onFeedback]
*/
async action(capability, payload, options) {
const ws = await this._ensureWs();
@minggangw minggangw changed the title [Web runtime] Add WebSocket action support [Web runtime] Add WebSocket action support (2/3) Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add action capability dispatch

3 participants