cometchat-js-v5-sdk
SkillWeb & browsingAdd voice & video calling to any web app FROM SCRATCH with the headless CometChat Calls SDK v5 (`@cometchat/calls-sdk-javascript@5`), no prebuilt UI Kit. init→login→generateToken→joinSession, event listeners, in-call actions (mute/video/screen-share/record/layout), meet-style session rooms AND 1:1 ringing (Chat SDK signaling + Calls SDK media). Triggers: 'add calling from scratch', 'standalone video call', 'headless calls sdk', 'build my own call UI', 'meeting room join by session id', 'one-on-one ringing call without uikit'.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cometchat-js-v5-sdk skill
What this skill tells your AI
The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-js-v5-sdk/SKILL.md and read by ahel’s review.
Ground truth:
@cometchat/calls-sdk-javascript@5+ catalogweb-calls-v5.json(the closed symbol list — everyCometChatCalls.*below exists in it). Official docs:/calls/javascript/**= v5 · Docs MCP. Fetch exactSessionSettingsfields, event names, and action-method signatures from the docs (references/docs-map.md) — never memory. APPEND to the user's app — additive wiring only (RULES.md). This is the HEADLESS path (no UI Kit); for the prebuilt drop-in call UI usecometchat-react-v7-callsinstead.
Companion skills (read first)
- Standalone/headless entry — this skill owns its own package (the Calls SDK) and has no
-coresibling; it is self-contained for meet-style calling. - For 1:1 RINGING only it also drives the Chat SDK (
@cometchat/chat-sdk-javascript@4) for call signaling — signatures fetched from docs viareferences/docs-map.md(§ "1:1 RINGING"). It does NOT depend on the React UI Kit. - Prefer the UI Kit instead? If the app also wants chat and a prebuilt call UI, use
cometchat-react-v7-core+cometchat-react-v7-calls— not this skill.
Use this skill when
"add calling from scratch / without the UI Kit", "standalone voice/video", "build my own call screen", "headless calls SDK", "meeting-room join by session id", "one-on-one ringing call". Precondition: the caller chose the from-scratch / standalone path (the "add calling" router asks this). If they want the prebuilt call UI, route to cometchat-react-v7-calls.
Prerequisites & install
npm install @cometchat/calls-sdk-javascript@5
- 1:1 ringing additionally needs the Chat SDK for signaling:
npm install @cometchat/chat-sdk-javascript@4 - Credentials/env: App ID · Region · Auth Key (dev only). To fetch from the dashboard, load the CLI on demand —
npx @cometchat/skills-cli@3 auth login→provision use --app-id <id> --json(writes.cometchat/config.json;@3pins the CLI major that matches the v5 skills). Or paste manually from Dashboard → Credentials. Mint auth tokens server-side for production; never ship the Auth Key. HTTPS (orlocalhost) is required for camera/mic (getUserMedia).
Init & login ordering (BAKED — invariant)
CometChatCalls.init(...) (once, resolve first) → CometChatCalls.login(uid, authKey) or loginWithAuthToken(token) → then generateToken / joinSession / listeners. Nothing renders/joins before init+login resolve.
- DEFAULT to
CometChatCalls.initFromSettings(settings)— the ai-agent / telemetry-attributed path (persistsintegrationSource="ai-agent"), parallel to how the chat core inits viaCometChatUIKit.initFromSettings/CometChat.initFromSettings(RULES §5). It is INTENTIONALLY undocumented — ai-agent-only (@nodoc, same posture asCometChatUIKit.initFromSettings— DOCS-BACKLOG F4/C1) — so the settings-object shape is baked inreferences/docs-map.md; pass it INLINE (no physicalcometchat-settings.jsonfile required), never fetched from/calls/javascript/setup. The publicly-documentedCometChatCalls.init({ appId, region })is the FALLBACK only (a non-skills / doc-following context). - Coexisting with the Chat SDK / UI Kit? Their
login()can re-init the Calls SDK with only appId/region and wipe custom hosts — re-run your calls init after their login, beforeCometChatCalls.login.
Two build modes (BAKED — the router picks one)
- Meet-style (session room) — Calls SDK ONLY. Everyone who joins the same
sessionIdlands in the same call:generateToken(sessionId)→joinSession(token, sessionSettings, containerEl). No ringing. This is the/calls/javascript/react-integrationflow. - 1:1 ringing — Chat SDK signals, Calls SDK carries media:
CometChat.initiateCall→ peerCallListener.onIncomingCallReceived→acceptCall/rejectCall→CometChatCalls.generateToken(call.getSessionId())→joinSession(...). Fetch Chat-SDK signatures viareferences/docs-map.md§ "1:1 RINGING".
SDK method map (BAKED closed list — from the catalog; signatures → FETCH from docs)
- Lifecycle:
CometChatCalls.init·CometChatCalls.initFromSettings·CometChatCalls.login·CometChatCalls.loginWithAuthToken·CometChatCalls.logout·CometChatCalls.getLoggedInUser·CometChatCalls.isUserLoggedIn - Session:
CometChatCalls.generateToken·CometChatCalls.joinSession·CometChatCalls.leaveSession(startSessionis deprecated → usejoinSession) - Events:
CometChatCalls.addEventListener(eventName, cb, { signal? }) → unsubscribe()(event names: FETCH the full list from/calls/javascript/events) - In-call actions — ⚠️ for CUSTOM controls ONLY; the default
joinSessionUI already renders all of these (see the first pitfall). Only reach for them when the user EXPLICITLY asks to replace the built-in controls:muteAudio/unmuteAudio/toggleAudio·pauseVideo/resumeVideo/toggleVideo·setLayout·startRecording/stopRecording·startScreenSharing/stopScreenSharing·raiseHand/lowerHand·switchCamera·pinParticipant/unpinParticipant·showParticipantList/hideParticipantList - Devices:
getAudioInputDevices·getAudioOutputDevices·getVideoInputDevices·getCurrent*Device - Call logs:
CometChatCalls.CallLogRequestBuilder→fetchNext()(paginated; shape → docs) - Constants:
CometChatCalls.constants.LAYOUT(TILE/SIDEBAR/SPOTLIGHT) ·.TYPE(VOICE/VIDEO) ·.CAMERA_FACING
This map is a curated highlight, NOT the full surface — the AUTHORITATIVE closed list is the
web-calls-v5.jsoncatalog (83 symbols; it also carriestoggleHand/toggleParticipantList/endSessionForAll/muteParticipant/pauseParticipantVideo/setChatButtonUnreadCount/switchToVideoCall, device setters (setAudioInputDevice…), the virtual-background methods,startStreaming/stopStreaming(RTMP live-streaming — withstreamUrl/streamKey/hideStreamingButtoninSessionSettings; neither the SKILL map above nor the/calls/javascript/actionsdoc foregrounds it, but it is real),startTranscription/stopTranscription(v5.0.5 — see/calls/javascript/transcription), andTranscriptRequestBuilder, among others). A symbol is real iff it's in the catalog — confirm THERE (not just this map), then fetch its exact signature/params from the docs page inreferences/docs-map.md.
Listener lifecycle (BAKED)
addEventListener RETURNS an unsubscribe function — collect them and call every one on teardown (React: in the effect cleanup), and CometChatCalls.leaveSession() on unmount. Register listeners BEFORE joinSession. Never leak. You can also pass an AbortSignal via the { signal } option for bulk teardown.
Least-code recipe (meet-style, framework-agnostic)
// STRICT-TS-CLEAN: type the settings with the EXPORTED SessionSettings, narrow region.
import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
import type { SessionSettings } from "@cometchat/calls-sdk-javascript"; // exported; SessionType/Layout are NOT
1. await CometChatCalls.initFromSettings({ appId, region: region as "us"|"eu"|"in", credentials: { authKey: AUTH_KEY }, callsSDK: {}, chatSDK: {}, uiKit: {} }) // ai-agent telemetry default (integrationSource="ai-agent"); init({appId,region}) is the public-doc fallback
2. await CometChatCalls.login(uid, AUTH_KEY) // or loginWithAuthToken(token)
3. const { token } = await CometChatCalls.generateToken(sessionId)
4. const unsub = CometChatCalls.addEventListener("onSessionLeft", () => cleanup())
5. const callSettings: SessionSettings = { sessionType: "VIDEO", layout: "TILE" } // annotate → literals narrow
await CometChatCalls.joinSession(token, callSettings, containerEl)
6. // NO control buttons needed — joinSession's UI ALREADY renders mute/video/screen-share/raise-hand/leave.
7. // teardown → unsub(); CometChatCalls.leaveSession()
The containerEl MUST have real dimensions — the SDK renders its call surface into it. Fetch the full SessionSettings field list from /calls/javascript/session-settings. (In plain JS drop the annotations; the doc pages show that JS form.)
Framework notes (same SDK, per-framework glue)
The recipe above is framework-agnostic; the only per-framework part is WHERE you register listeners / mount the container / tear down. Verified live on React and Angular.
- React: provider or component — init via
CometChatCalls.initFromSettings(...)(the telemetry-attributed default —integrationSource="ai-agent";init({appId,region})is the public-doc fallback), then register listeners +joinSessionin auseEffect; teardown in the effect cleanup (call every unsubscribe +leaveSession). Recipe:/calls/javascript/react-integration. - Angular: a DI service wrapping
CometChatCalls(init viaCometChatCalls.initFromSettings(...)— the telemetry-attributed default (integrationSource="ai-agent";init({appId,region})is the public-doc fallback) → login,generateToken, typedjoinSession,leaveSession; expose readiness via an RxJSBehaviorSubject) + a component with a sized@ViewChild('callContainer') ElementRefcontainer; register listeners BEFOREjoinSession; teardown inngOnDestroy(unsubscribe all +leaveSession). Recipe:/calls/javascript/angular-integration— but ⚠️ THREE things to override:- (a) its example wires external Mute/Video/Leave buttons — IGNORE them (pitfall #1:
joinSession's UI already has the controls); - (b) it targets legacy
@NgModule/app.module.ts— a modernng newis standalone (bootstrapApplication+app.config.ts, classApp), so use the standalone variant; - (c) ⚠️ NgZone / change detection (the silent dead-state). CometChat SDK callbacks — event listeners AND the
login/generateToken/joinSessionpromise resolutions — fire OUTSIDE Angular's zone, so any component state you set inside them won't trigger change detection (symptom: readiness/call buttons silently never enable, even though the SDK succeeded). Fix: drive the template off yourBehaviorSubjectvia theasyncpipe, AND/OR wrap state writes inthis.zone.run(() => …)(injectNgZone) or callChangeDetectorRef.detectChanges(). Not optional — the app looks broken without it.
- (a) its example wires external Mute/Video/Leave buttons — IGNORE them (pitfall #1:
Common pitfalls (BAKED)
- Don't duplicate the built-in call controls (the #1 mistake).
joinSessionrenders a COMPLETE call UI — mute, camera on/off, screen-share, raise-hand, participant list, layout switch, and the red leave/end button are ALL built into the surface it mounts incontainerEl. Do NOT add your own Mute / Start-video / Share-screen / Leave buttons around the container: they are redundant, duplicate the SDK's own controls, and drift out of sync with the real call state. ThemuteAudio/pauseVideo/leaveSession/… methods are for CUSTOM controls ONLY — reach for them just when the user EXPLICITLY asks to replace the default controls (and hide the built-in ones first viaSessionSettings—hideControlPanelfor the whole bar, or per-button flags likehideToggleAudioButton/hideRaiseHandButton/hideChatButton; the canonical recipe is/calls/javascript/custom-control-panel, fields on/calls/javascript/session-settings). Default = render the call surface and stop. - Zero-dimension container —
joinSessionmounts intocontainerEl; if it hasheight:0the call renders invisibly. Give it explicit size (e.g.height: 500px/100dvh). - HTTP (not HTTPS) —
getUserMedianeeds a secure context; camera/mic silently fail offlocalhost. - Joining before init+login resolve —
generateToken/joinSessionreject; alwaysawaitinit then login first. - Leaked listeners / no
leaveSession— everyaddEventListenerunsubscribe must run on teardown; callleaveSession()on unmount. startSessionis deprecated — usejoinSession; don't pass the oldCallSettingsbuilder where a plainSessionSettingsobject is expected.- Host wipe on coexisting Chat-SDK login — re-init the Calls SDK after the Chat SDK/UI Kit logs in (see Init ordering).
- version_conflict — the Calls SDK is major 5, distinct from the Chat SDK's v4; do not "upgrade" the Chat SDK to a non-existent v7.
- Assuming a signature — event names,
SessionSettingsfields, and action params are FETCHED from docs, never guessed. - 1:1 ringing:
CometChat.Callused only as a TYPE tripsTS6133— in strict TS, importingCometChatand referencingCometChat.Callin type positions only (never as a value) fails with'CometChat' is declared but its value is never read. Import the concrete type instead:import { CometChat } from "@cometchat/chat-sdk-javascript"for the VALUES you call (initiateCall/acceptCall/addCallListener) andimport type { Call } from "@cometchat/chat-sdk-javascript"for the type. (Same class as theSessionSettings/CometChatCallsstrict-TS trap.) - Strict-TS widening (the doc's bare-object form doesn't compile as-is) — the doc pages pass
joinSession(token, { sessionType: "VIDEO", layout: "TILE" }, el)andinit({ appId, region })as plain JS. In a strict-TS app (the stock Vitereact-tstemplate:strict+verbatimModuleSyntax+noUnusedLocals) those literals WIDEN tostringand failtsc(TS2345 vsSessionSettings; TS2322 forregion). Fix:import type { SessionSettings }(it's exported;SessionType/Layoutare NOT) and annotate the settings object —const s: SessionSettings = {…}(orsatisfies SessionSettings) — and narrowregionto"us"|"eu"|"in".
Verify it works
- Tier-1 catalog: every
CometChatCalls.*symbol emitted appears inweb-calls-v5.json(node test-suite/scripts/verify-catalog.mjs --family web-calls-v5). - Tier-2 fences: the emit type-checks against the installed
@cometchat/calls-sdk-javascript@5.d.ts. - Tier-3b headless smoke:
node test-suite/scripts/sdk-smoke.mjs --family web-calls-v5 [--live|--dry]runs init→login→generateToken→(join wiring)→listener-teardown. Media/joinSessionneeds a real WebRTC/DOM context, so the node smoke covers the token+listener round-trip (--dryproves wiring without a backend); the actual call render is verified in a browser harness. Flag "dry-mock only, not live-certified" honestly where true.
Signals
- GitHub stars
- 109
- Forks
- 2
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
cometchat-js-v5-sdk- Source
- github.com/cometchat/cometchat-skills