Conversation
| }; | ||
|
|
||
| return () => { | ||
| delete this.handlers[eventName][handlerId]; |
Check warning
Code scanning / CodeQL
Prototype-polluting assignment Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general, to fix prototype-pollution risks from user-controlled property names, avoid using untrusted strings as keys on plain JavaScript objects that inherit from Object.prototype. Prefer Map/WeakMap, or at least validate/restrict keys against dangerous values like __proto__, constructor, and prototype.
For this code, the most direct, behavior-preserving fix is to change the handler registries from Record<string, ...> objects into Map instances. Map does not have the special prototype-related keys and is safe against attacks using __proto__ etc. We can keep the existing API the same: registerHandler still takes eventName: string, handler lookup by tool_name remains conceptually similar, and the return value (an unregister function) still works. Concretely:
- Change the fields:
handlersfromRecord<string, Record<string, ToolCallHandler>> = {}toMap<string, Map<string, ToolCallHandler>> = new Map().genericHandlersfromRecord<string, ToolCallHandler> = {}toMap<string, ToolCallHandler> = new Map().pendingCallsfromRecord<string, PendingToolCall> = {}toMap<string, PendingToolCall> = new Map().
- Update all uses:
clearPendingCalls()becomesthis.pendingCalls.clear().- In
registerHandler:- For the wildcard case (
eventName === '*'), usethis.genericHandlers.set(handlerId, handler)andthis.genericHandlers.delete(handlerId). - For normal events: retrieve or create an inner
Mapwithlet handlersForEvent = this.handlers.get(eventName) ?? new Map();and thenhandlersForEvent.set(handlerId, handler); this.handlers.set(eventName, handlersForEvent);. The unregister function then doeshandlersForEvent.delete(handlerId)(or re-fetches the map safely).
- For the wildcard case (
- In
processToolCallStartedEvent:- Replace
const handlersForTool = this.handlers[tool_name] || {};with something likeconst handlersForTool = this.handlers.get(tool_name); const handlers = handlersForTool ? Array.from(handlersForTool.values()) : [];. - Replace
Object.values(this.genericHandlers)withArray.from(this.genericHandlers.values()). - Replace
this.pendingCalls[toolCallEvent.tool_call_id] = { ... }withthis.pendingCalls.set(toolCallEvent.tool_call_id, { ... }).
- Replace
- Elsewhere in
ToolCallManager(not fully shown), any other use ofthis.handlers,this.genericHandlers, orthis.pendingCallsmust be converted to appropriateMapoperations (get,set,delete,has,values, etc.). Because you asked me to only touch code shown, I’ll limit explicit replacements to the visible parts, but you should mirror this pattern for other references in the same file.
No new imports are required; Map is a built-in.
There was a problem hiding this comment.
1 issue found across 10 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/modules/ToolCallManager.ts">
<violation number="1" location="src/modules/ToolCallManager.ts:249">
P2: Completed tool call events should expose the tool result, not the original arguments. This mapping loses the output payload for clients.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Pull request overview
Refactors WebRTC “tool call” event handling by introducing explicit started/completed/failed event types and routing them through a centralized ToolCallManager, with a public registration API exposed on AnamClient.
Changes:
- Added new WebRTC tool-call event models and corresponding data-channel message types.
- Introduced tool-call payload types plus a
ToolCallManagerto process/dispatch tool-call lifecycle events. - Wired
StreamingClientandAnamClientto use the sharedToolCallManagerand exposedregisterToolCallHandler.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/streaming/index.ts | Adds exports for tool-call payload types (streaming barrel update). |
| src/types/streaming/WebRtcToolCallEvent.ts | Introduces WebRTC wire-format interfaces for tool-call started/completed/failed. |
| src/types/streaming/ToolCallEvents.ts | Defines SDK-facing tool-call payload shapes (camelCase). |
| src/types/streaming/DataChannelMessage.ts | Adds new data channel message type constants for tool-call lifecycle events. |
| src/types/events/internal/InternalEventCallbacks.ts | Extends internal callback typings to include tool-call lifecycle events. |
| src/types/events/internal/InternalEvent.ts | Adds new internal event enum entries for tool-call lifecycle events. |
| src/modules/index.ts | Removes ToolCallManager from the modules barrel export. |
| src/modules/ToolCallManager.ts | Implements handler registration + tool-call lifecycle processing, payload conversion, and execution timing. |
| src/modules/StreamingClient.ts | Routes tool-call data-channel messages into internal events and ToolCallManager; maintains client-tool backward emission on completed events. |
| src/AnamClient.ts | Instantiates and passes ToolCallManager into StreamingClient; exposes registerToolCallHandler. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
653cddf to
0c7af9c
Compare
0c7af9c to
f3fd675
Compare
Summary by cubic
Refactored tool calls to a start/completed/failed lifecycle with a centralized ToolCallManager and a simple handler API. WebRTC TOOL_CALL_* events are handled end-to-end; client tool compatibility is preserved by emitting the legacy ClientToolEvent on start and by still accepting legacy CLIENT_TOOL_EVENT messages.
New Features
Refactors
Written for commit f3fd675. Summary will update on new commits.