@happyrobot-ai/sdk 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/chat/index.d.ts +17 -0
- package/chat/index.js +20 -0
- package/chat/index.mjs +3 -0
- package/chat-client.mjs +1 -2
- package/client.d.ts +3 -0
- package/client.js +4 -0
- package/client.mjs +1 -2
- package/core/errors.mjs +1 -2
- package/core/http.mjs +1 -2
- package/core/pagination.mjs +1 -2
- package/core/sse.mjs +1 -2
- package/core/types.mjs +0 -1
- package/helpers/index.mjs +1 -2
- package/helpers/template-workflows.mjs +1 -2
- package/helpers/trigger-and-wait.mjs +1 -2
- package/helpers/voice-agent.mjs +1 -2
- package/index.d.ts +2 -2
- package/index.js +3 -3
- package/index.mjs +3 -4
- package/package.json +19 -1
- package/resources/adversarial-suites.mjs +1 -2
- package/resources/adversarial-tests.mjs +1 -2
- package/resources/api-key.mjs +1 -2
- package/resources/artifacts.mjs +1 -2
- package/resources/audit-remarks.mjs +1 -2
- package/resources/billing.mjs +1 -2
- package/resources/chat.mjs +1 -2
- package/resources/contacts.mjs +1 -2
- package/resources/custom-evals.mjs +1 -2
- package/resources/integrations.mjs +1 -2
- package/resources/issues.mjs +1 -2
- package/resources/knowledge-bases.mjs +1 -2
- package/resources/mcp.mjs +1 -2
- package/resources/messages.mjs +1 -2
- package/resources/nodes.mjs +1 -2
- package/resources/northstars.mjs +1 -2
- package/resources/phone-numbers.mjs +1 -2
- package/resources/runs.mjs +1 -2
- package/resources/sessions.mjs +1 -2
- package/resources/sip-trunks.mjs +1 -2
- package/resources/variables.mjs +1 -2
- package/resources/versions.mjs +1 -2
- package/resources/voice.d.ts +29 -0
- package/resources/voice.js +40 -0
- package/resources/voice.mjs +3 -0
- package/resources/workflow-folders.mjs +1 -2
- package/resources/workflows.mjs +1 -2
- package/types/adversarial-suites.types.d.ts +26 -0
- package/types/adversarial-suites.types.js +6 -0
- package/types/adversarial-suites.types.mjs +1 -0
- package/types/adversarial-tests.types.d.ts +21 -0
- package/types/adversarial-tests.types.js +6 -0
- package/types/adversarial-tests.types.mjs +1 -0
- package/types/artifacts.types.d.ts +4 -0
- package/types/artifacts.types.js +3 -0
- package/types/artifacts.types.mjs +1 -0
- package/types/audit-remarks.types.d.ts +19 -0
- package/types/audit-remarks.types.js +6 -0
- package/types/audit-remarks.types.mjs +1 -0
- package/types/chat.types.d.ts +145 -0
- package/types/chat.types.js +3 -0
- package/types/chat.types.mjs +1 -0
- package/types/common.types.d.ts +19 -0
- package/types/common.types.js +7 -0
- package/types/common.types.mjs +1 -0
- package/types/contacts.types.d.ts +6 -0
- package/types/contacts.types.js +6 -0
- package/types/contacts.types.mjs +1 -0
- package/types/custom-evals.types.d.ts +19 -0
- package/types/custom-evals.types.js +6 -0
- package/types/custom-evals.types.mjs +1 -0
- package/types/integrations.types.d.ts +45 -0
- package/types/integrations.types.js +6 -0
- package/types/integrations.types.mjs +1 -0
- package/types/issues.types.d.ts +11 -0
- package/types/issues.types.js +6 -0
- package/types/issues.types.mjs +1 -0
- package/types/knowledge-bases.types.d.ts +21 -0
- package/types/knowledge-bases.types.js +7 -0
- package/types/knowledge-bases.types.mjs +1 -0
- package/types/mcp.types.d.ts +10 -0
- package/types/mcp.types.js +6 -0
- package/types/mcp.types.mjs +1 -0
- package/types/messages.types.d.ts +9 -0
- package/types/messages.types.js +6 -0
- package/types/messages.types.mjs +1 -0
- package/types/nodes.types.d.ts +12 -0
- package/types/nodes.types.js +6 -0
- package/types/nodes.types.mjs +1 -0
- package/types/northstars.types.d.ts +18 -0
- package/types/northstars.types.js +6 -0
- package/types/northstars.types.mjs +1 -0
- package/types/phone-numbers.types.d.ts +24 -0
- package/types/phone-numbers.types.js +6 -0
- package/types/phone-numbers.types.mjs +1 -0
- package/types/runs.types.d.ts +16 -0
- package/types/runs.types.js +6 -0
- package/types/runs.types.mjs +1 -0
- package/types/sessions.types.d.ts +51 -0
- package/types/sessions.types.js +6 -0
- package/types/sessions.types.mjs +1 -0
- package/types/sip-trunks.types.d.ts +11 -0
- package/types/sip-trunks.types.js +6 -0
- package/types/sip-trunks.types.mjs +1 -0
- package/types/variables.types.d.ts +10 -0
- package/types/variables.types.js +6 -0
- package/types/variables.types.mjs +1 -0
- package/types/versions.types.d.ts +22 -0
- package/types/versions.types.js +6 -0
- package/types/versions.types.mjs +1 -0
- package/types/voice.types.d.ts +13 -0
- package/types/voice.types.js +3 -0
- package/types/voice.types.mjs +1 -0
- package/types/workflow-folders.types.d.ts +9 -0
- package/types/workflow-folders.types.js +6 -0
- package/types/workflow-folders.types.mjs +1 -0
- package/types/workflows.types.d.ts +24 -0
- package/types/workflows.types.js +7 -0
- package/types/workflows.types.mjs +1 -0
- package/voice/index.d.ts +22 -0
- package/voice/index.js +25 -0
- package/voice/index.mjs +3 -0
- package/voice-client.d.ts +87 -0
- package/voice-client.js +148 -0
- package/voice-client.mjs +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./runs.types.js";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session types extracted from Zod schemas.
|
|
3
|
+
*/
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
import type { ListSessionsQuerySchema, SessionItemSchema, PaginatedSessionsResponseSchema, ListMessagesQuerySchema, MessageItemSchema, PaginatedMessagesResponseSchema, StreamQuerySchema } from "../../routes/sessions/schemas";
|
|
6
|
+
export type ListSessionsQuery = z.input<typeof ListSessionsQuerySchema>;
|
|
7
|
+
export type SessionItem = z.infer<typeof SessionItemSchema>;
|
|
8
|
+
export type PaginatedSessionsResponse = z.infer<typeof PaginatedSessionsResponseSchema>;
|
|
9
|
+
export type ListMessagesQuery = z.input<typeof ListMessagesQuerySchema>;
|
|
10
|
+
export type MessageItem = z.infer<typeof MessageItemSchema>;
|
|
11
|
+
export type PaginatedMessagesResponse = z.infer<typeof PaginatedMessagesResponseSchema>;
|
|
12
|
+
export type StreamQuery = z.input<typeof StreamQuerySchema>;
|
|
13
|
+
/** Payload for SSE "message" events from the session stream. */
|
|
14
|
+
export interface StreamMessagePayload {
|
|
15
|
+
id: string;
|
|
16
|
+
session_id: string;
|
|
17
|
+
role: string;
|
|
18
|
+
content: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
is_filler?: boolean;
|
|
21
|
+
is_interrupted?: boolean;
|
|
22
|
+
tool_calls?: unknown;
|
|
23
|
+
artifacts?: unknown;
|
|
24
|
+
}
|
|
25
|
+
/** Union of all SSE event data types emitted by the session stream. */
|
|
26
|
+
export type SessionStreamEvent = {
|
|
27
|
+
event: "connected";
|
|
28
|
+
data: {
|
|
29
|
+
session_id: string;
|
|
30
|
+
session_status: string;
|
|
31
|
+
};
|
|
32
|
+
} | {
|
|
33
|
+
event: "message";
|
|
34
|
+
data: StreamMessagePayload;
|
|
35
|
+
id?: string;
|
|
36
|
+
} | {
|
|
37
|
+
event: "backfill_complete";
|
|
38
|
+
data: {
|
|
39
|
+
count: number;
|
|
40
|
+
};
|
|
41
|
+
} | {
|
|
42
|
+
event: "session_ended";
|
|
43
|
+
data: {
|
|
44
|
+
status: string;
|
|
45
|
+
};
|
|
46
|
+
} | {
|
|
47
|
+
event: "error";
|
|
48
|
+
data: {
|
|
49
|
+
message: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./sessions.types.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SIP trunk types extracted from Zod schemas.
|
|
3
|
+
*/
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
import type { SipTrunkResponseSchema, ListSipTrunksResponseSchema, CreateSipTrunkBodySchema, CreateSipTrunkBulkBodySchema, UpdateSipTrunkBodySchema, SipTrunkOptionsResponseSchema } from "../../routes/sip-trunks/schemas";
|
|
6
|
+
export type SipTrunkResponse = z.infer<typeof SipTrunkResponseSchema>;
|
|
7
|
+
export type ListSipTrunksResponse = z.infer<typeof ListSipTrunksResponseSchema>;
|
|
8
|
+
export type CreateSipTrunkBody = z.input<typeof CreateSipTrunkBodySchema>;
|
|
9
|
+
export type CreateSipTrunkBulkBody = z.input<typeof CreateSipTrunkBulkBodySchema>;
|
|
10
|
+
export type UpdateSipTrunkBody = z.input<typeof UpdateSipTrunkBodySchema>;
|
|
11
|
+
export type SipTrunkOptionsResponse = z.infer<typeof SipTrunkOptionsResponseSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./sip-trunks.types.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Variable types extracted from Zod schemas.
|
|
3
|
+
*/
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
import type { VariableResponseSchema, ListVariablesQuerySchema, PaginatedVariablesResponseSchema, CreateVariableBodySchema, UpdateVariableBodySchema } from "../../routes/workflows/:workflow_id/variables/schemas";
|
|
6
|
+
export type VariableResponse = z.infer<typeof VariableResponseSchema>;
|
|
7
|
+
export type ListVariablesQuery = z.input<typeof ListVariablesQuerySchema>;
|
|
8
|
+
export type PaginatedVariablesResponse = z.infer<typeof PaginatedVariablesResponseSchema>;
|
|
9
|
+
export type CreateVariableBody = z.input<typeof CreateVariableBodySchema>;
|
|
10
|
+
export type UpdateVariableBody = z.input<typeof UpdateVariableBodySchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./variables.types.js";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version types extracted from Zod schemas.
|
|
3
|
+
*/
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
import type { VersionWithNodesSummarySchema, UpdateVersionBodySchema, UpdateVersionResponseSchema, ForkVersionResponseSchema, PublishBodySchema, PublishResponseSchema, PublishErrorResponseSchema, VersionStatusResponseSchema, ListNodesResponseSchema, AddNodesBodySchema, AddNodesResponseSchema, UpdateNodeBodySchema, GetSingleNodeResponseSchema } from "../../routes/versions/:version_id/schemas";
|
|
6
|
+
import type { PromptIssuesResponseSchema, PromptNodeIssuesSchema, PromptIssueSchema } from "../../routes/versions/:version_id/prompt-issues/get";
|
|
7
|
+
export type VersionWithNodesSummary = z.infer<typeof VersionWithNodesSummarySchema>;
|
|
8
|
+
export type UpdateVersionBody = z.input<typeof UpdateVersionBodySchema>;
|
|
9
|
+
export type UpdateVersionResponse = z.infer<typeof UpdateVersionResponseSchema>;
|
|
10
|
+
export type ForkVersionResponse = z.infer<typeof ForkVersionResponseSchema>;
|
|
11
|
+
export type PublishBody = z.input<typeof PublishBodySchema>;
|
|
12
|
+
export type PublishResponse = z.infer<typeof PublishResponseSchema>;
|
|
13
|
+
export type PublishErrorResponse = z.infer<typeof PublishErrorResponseSchema>;
|
|
14
|
+
export type VersionStatusResponse = z.infer<typeof VersionStatusResponseSchema>;
|
|
15
|
+
export type ListNodesResponse = z.infer<typeof ListNodesResponseSchema>;
|
|
16
|
+
export type AddNodesBody = z.input<typeof AddNodesBodySchema>;
|
|
17
|
+
export type AddNodesResponse = z.infer<typeof AddNodesResponseSchema>;
|
|
18
|
+
export type UpdateNodeBody = z.input<typeof UpdateNodeBodySchema>;
|
|
19
|
+
export type GetSingleNodeResponse = z.infer<typeof GetSingleNodeResponseSchema>;
|
|
20
|
+
export type PromptIssue = z.infer<typeof PromptIssueSchema>;
|
|
21
|
+
export type PromptNodeIssues = z.infer<typeof PromptNodeIssuesSchema>;
|
|
22
|
+
export type PromptIssuesResponse = z.infer<typeof PromptIssuesResponseSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./versions.types.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** POST /voice/tokens request body. */
|
|
2
|
+
export interface CreateVoiceTokenBody {
|
|
3
|
+
workflow_id: string;
|
|
4
|
+
data?: Record<string, unknown>;
|
|
5
|
+
env?: "production" | "staging" | "development";
|
|
6
|
+
}
|
|
7
|
+
/** POST /voice/tokens response. */
|
|
8
|
+
export interface CreateVoiceTokenResponse {
|
|
9
|
+
url: string;
|
|
10
|
+
token: string;
|
|
11
|
+
room_name: string;
|
|
12
|
+
run_id: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./voice.types.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow folder types extracted from Zod schemas.
|
|
3
|
+
*/
|
|
4
|
+
import type { z } from "zod";
|
|
5
|
+
import type { WorkflowFolderSchema, PaginatedFoldersResponseSchema, ListFoldersQuerySchema, CreateFolderBodySchema } from "../../routes/workflow-folders/schemas";
|
|
6
|
+
export type WorkflowFolder = z.infer<typeof WorkflowFolderSchema>;
|
|
7
|
+
export type PaginatedFoldersResponse = z.infer<typeof PaginatedFoldersResponseSchema>;
|
|
8
|
+
export type ListFoldersQuery = z.input<typeof ListFoldersQuerySchema>;
|
|
9
|
+
export type CreateFolderBody = z.input<typeof CreateFolderBodySchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./workflow-folders.types.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow types extracted from Zod schemas.
|
|
3
|
+
* Uses import type — erased at compile time.
|
|
4
|
+
*/
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
import type { ListWorkflowsQuerySchema, WorkflowListItemSchema, PaginatedWorkflowsResponseSchema, CreateWorkflowBodySchema, CreateWorkflowResponseSchema, WorkflowDetailResponseSchema, UpdateWorkflowBodySchema, UpdateWorkflowResponseSchema, DuplicateWorkflowBodySchema, DuplicateWorkflowResponseSchema, PaginatedTemplatesResponseSchema, ListTemplatesQuerySchema, WorkflowPublishResponseSchema, WorkflowPublishErrorResponseSchema, WorkflowUnpublishResponseSchema, CancelRunsResponseSchema, ListWorkflowVersionsQuerySchema, PaginatedWorkflowVersionsResponseSchema } from "../../routes/workflows/schemas";
|
|
7
|
+
export type ListWorkflowsQuery = z.input<typeof ListWorkflowsQuerySchema>;
|
|
8
|
+
export type WorkflowListItem = z.infer<typeof WorkflowListItemSchema>;
|
|
9
|
+
export type PaginatedWorkflowsResponse = z.infer<typeof PaginatedWorkflowsResponseSchema>;
|
|
10
|
+
export type CreateWorkflowBody = z.input<typeof CreateWorkflowBodySchema>;
|
|
11
|
+
export type CreateWorkflowResponse = z.infer<typeof CreateWorkflowResponseSchema>;
|
|
12
|
+
export type WorkflowDetailResponse = z.infer<typeof WorkflowDetailResponseSchema>;
|
|
13
|
+
export type UpdateWorkflowBody = z.input<typeof UpdateWorkflowBodySchema>;
|
|
14
|
+
export type UpdateWorkflowResponse = z.infer<typeof UpdateWorkflowResponseSchema>;
|
|
15
|
+
export type DuplicateWorkflowBody = z.input<typeof DuplicateWorkflowBodySchema>;
|
|
16
|
+
export type DuplicateWorkflowResponse = z.infer<typeof DuplicateWorkflowResponseSchema>;
|
|
17
|
+
export type ListTemplatesQuery = z.input<typeof ListTemplatesQuerySchema>;
|
|
18
|
+
export type PaginatedTemplatesResponse = z.infer<typeof PaginatedTemplatesResponseSchema>;
|
|
19
|
+
export type WorkflowPublishResponse = z.infer<typeof WorkflowPublishResponseSchema>;
|
|
20
|
+
export type WorkflowPublishErrorResponse = z.infer<typeof WorkflowPublishErrorResponseSchema>;
|
|
21
|
+
export type WorkflowUnpublishResponse = z.infer<typeof WorkflowUnpublishResponseSchema>;
|
|
22
|
+
export type CancelRunsResponse = z.infer<typeof CancelRunsResponseSchema>;
|
|
23
|
+
export type ListWorkflowVersionsQuery = z.input<typeof ListWorkflowVersionsQuerySchema>;
|
|
24
|
+
export type PaginatedWorkflowVersionsResponse = z.infer<typeof PaginatedWorkflowVersionsResponseSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./workflows.types.js";
|
package/voice/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyrobot-ai/sdk/voice — Browser-side voice client (WebRTC via LiveKit).
|
|
3
|
+
*
|
|
4
|
+
* Requires `livekit-client` as a peer dependency.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { HappyRobotVoiceClient } from "@happyrobot-ai/sdk/voice";
|
|
9
|
+
*
|
|
10
|
+
* const voice = new HappyRobotVoiceClient({ url, token });
|
|
11
|
+
* const connection = await voice.connect({
|
|
12
|
+
* onConnected: () => console.log("Connected!"),
|
|
13
|
+
* onAgentConnected: (p) => console.log("Agent joined:", p.identity),
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* // Later…
|
|
17
|
+
* await connection.disconnect();
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export { HappyRobotVoiceClient } from "../voice-client";
|
|
21
|
+
export type { VoiceConnectionHandlers, VoiceConnection } from "../voice-client";
|
|
22
|
+
export type { CreateVoiceTokenBody, CreateVoiceTokenResponse, } from "../types/voice.types";
|
package/voice/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @happyrobot-ai/sdk/voice — Browser-side voice client (WebRTC via LiveKit).
|
|
4
|
+
*
|
|
5
|
+
* Requires `livekit-client` as a peer dependency.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { HappyRobotVoiceClient } from "@happyrobot-ai/sdk/voice";
|
|
10
|
+
*
|
|
11
|
+
* const voice = new HappyRobotVoiceClient({ url, token });
|
|
12
|
+
* const connection = await voice.connect({
|
|
13
|
+
* onConnected: () => console.log("Connected!"),
|
|
14
|
+
* onAgentConnected: (p) => console.log("Agent joined:", p.identity),
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Later…
|
|
18
|
+
* await connection.disconnect();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.HappyRobotVoiceClient = void 0;
|
|
23
|
+
var voice_client_1 = require("../voice-client");
|
|
24
|
+
Object.defineProperty(exports, "HappyRobotVoiceClient", { enumerable: true, get: function () { return voice_client_1.HappyRobotVoiceClient; } });
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/voice/index.mjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HappyRobotVoiceClient — browser-side client for voice calls with AI agents.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `livekit-client` Room with HappyRobot defaults for audio-only calls.
|
|
5
|
+
* Requires `livekit-client` as a peer dependency.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { HappyRobotVoiceClient } from "@happyrobot-ai/sdk/voice";
|
|
10
|
+
*
|
|
11
|
+
* // Token comes from your server via client.voice.createToken()
|
|
12
|
+
* const voice = new HappyRobotVoiceClient({ url, token });
|
|
13
|
+
*
|
|
14
|
+
* const connection = await voice.connect({
|
|
15
|
+
* onConnected: () => console.log("Connected!"),
|
|
16
|
+
* onAgentConnected: (p) => console.log("Agent joined:", p.identity),
|
|
17
|
+
* onDisconnected: (reason) => console.log("Disconnected:", reason),
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Mute/unmute
|
|
21
|
+
* await connection.mute();
|
|
22
|
+
* await connection.unmute();
|
|
23
|
+
*
|
|
24
|
+
* // End the call
|
|
25
|
+
* await connection.disconnect();
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { Room } from "livekit-client";
|
|
29
|
+
export interface VoiceConnectionHandlers {
|
|
30
|
+
/** Room connection established. */
|
|
31
|
+
onConnected?: () => void;
|
|
32
|
+
/** Room disconnected. */
|
|
33
|
+
onDisconnected?: (reason?: string) => void;
|
|
34
|
+
/** AI agent participant joined the room. */
|
|
35
|
+
onAgentConnected?: (participant: {
|
|
36
|
+
identity: string;
|
|
37
|
+
name: string;
|
|
38
|
+
}) => void;
|
|
39
|
+
/** Remote audio track subscribed — audio will play automatically. */
|
|
40
|
+
onTrackSubscribed?: (track: {
|
|
41
|
+
kind: string;
|
|
42
|
+
source: string;
|
|
43
|
+
/** Attach to a DOM element. Returns the HTMLMediaElement created. */
|
|
44
|
+
attach: () => HTMLMediaElement;
|
|
45
|
+
}) => void;
|
|
46
|
+
/** Remote audio track unsubscribed. */
|
|
47
|
+
onTrackUnsubscribed?: (track: {
|
|
48
|
+
kind: string;
|
|
49
|
+
source: string;
|
|
50
|
+
}) => void;
|
|
51
|
+
/** Connection temporarily lost — attempting to reconnect. */
|
|
52
|
+
onReconnecting?: () => void;
|
|
53
|
+
/** Successfully reconnected after a temporary disconnect. */
|
|
54
|
+
onReconnected?: () => void;
|
|
55
|
+
/** An error occurred. */
|
|
56
|
+
onError?: (error: Error) => void;
|
|
57
|
+
}
|
|
58
|
+
export interface VoiceConnection {
|
|
59
|
+
/** Disconnect from the room and end the call. */
|
|
60
|
+
disconnect(): Promise<void>;
|
|
61
|
+
/** Mute the local microphone. */
|
|
62
|
+
mute(): Promise<void>;
|
|
63
|
+
/** Unmute the local microphone. */
|
|
64
|
+
unmute(): Promise<void>;
|
|
65
|
+
/** Whether the local microphone is currently muted. */
|
|
66
|
+
isMuted(): boolean;
|
|
67
|
+
/** The underlying LiveKit Room instance for advanced use cases. */
|
|
68
|
+
readonly room: Room;
|
|
69
|
+
}
|
|
70
|
+
export interface VoiceClientConfig {
|
|
71
|
+
/** LiveKit WebSocket URL from `client.voice.createToken()`. */
|
|
72
|
+
url: string;
|
|
73
|
+
/** LiveKit access token from `client.voice.createToken()`. */
|
|
74
|
+
token: string;
|
|
75
|
+
}
|
|
76
|
+
export declare class HappyRobotVoiceClient {
|
|
77
|
+
private readonly url;
|
|
78
|
+
private readonly token;
|
|
79
|
+
constructor(config: VoiceClientConfig);
|
|
80
|
+
/**
|
|
81
|
+
* Connect to the voice call room and enable the microphone.
|
|
82
|
+
*
|
|
83
|
+
* Returns a `VoiceConnection` with `mute()`, `unmute()`, and `disconnect()` methods.
|
|
84
|
+
* Pass event handlers to react to room lifecycle events and remote tracks.
|
|
85
|
+
*/
|
|
86
|
+
connect(handlers?: VoiceConnectionHandlers): Promise<VoiceConnection>;
|
|
87
|
+
}
|
package/voice-client.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HappyRobotVoiceClient — browser-side client for voice calls with AI agents.
|
|
4
|
+
*
|
|
5
|
+
* Wraps `livekit-client` Room with HappyRobot defaults for audio-only calls.
|
|
6
|
+
* Requires `livekit-client` as a peer dependency.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { HappyRobotVoiceClient } from "@happyrobot-ai/sdk/voice";
|
|
11
|
+
*
|
|
12
|
+
* // Token comes from your server via client.voice.createToken()
|
|
13
|
+
* const voice = new HappyRobotVoiceClient({ url, token });
|
|
14
|
+
*
|
|
15
|
+
* const connection = await voice.connect({
|
|
16
|
+
* onConnected: () => console.log("Connected!"),
|
|
17
|
+
* onAgentConnected: (p) => console.log("Agent joined:", p.identity),
|
|
18
|
+
* onDisconnected: (reason) => console.log("Disconnected:", reason),
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Mute/unmute
|
|
22
|
+
* await connection.mute();
|
|
23
|
+
* await connection.unmute();
|
|
24
|
+
*
|
|
25
|
+
* // End the call
|
|
26
|
+
* await connection.disconnect();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.HappyRobotVoiceClient = void 0;
|
|
31
|
+
const livekit_client_1 = require("livekit-client");
|
|
32
|
+
class HappyRobotVoiceClient {
|
|
33
|
+
url;
|
|
34
|
+
token;
|
|
35
|
+
constructor(config) {
|
|
36
|
+
if (!config.url)
|
|
37
|
+
throw new Error("url is required");
|
|
38
|
+
if (!config.token)
|
|
39
|
+
throw new Error("token is required");
|
|
40
|
+
this.url = config.url;
|
|
41
|
+
this.token = config.token;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Connect to the voice call room and enable the microphone.
|
|
45
|
+
*
|
|
46
|
+
* Returns a `VoiceConnection` with `mute()`, `unmute()`, and `disconnect()` methods.
|
|
47
|
+
* Pass event handlers to react to room lifecycle events and remote tracks.
|
|
48
|
+
*/
|
|
49
|
+
async connect(handlers = {}) {
|
|
50
|
+
// Create Room with HappyRobot defaults (matching platform use-webcall.tsx)
|
|
51
|
+
const room = new livekit_client_1.Room({
|
|
52
|
+
adaptiveStream: true,
|
|
53
|
+
dynacast: true,
|
|
54
|
+
audioCaptureDefaults: {
|
|
55
|
+
echoCancellation: true,
|
|
56
|
+
noiseSuppression: false,
|
|
57
|
+
},
|
|
58
|
+
publishDefaults: {
|
|
59
|
+
dtx: false,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
// Track mute state locally
|
|
63
|
+
let muted = false;
|
|
64
|
+
// ── Event listeners ──
|
|
65
|
+
room.on(livekit_client_1.RoomEvent.Connected, () => {
|
|
66
|
+
handlers.onConnected?.();
|
|
67
|
+
});
|
|
68
|
+
room.on(livekit_client_1.RoomEvent.Disconnected, (reason) => {
|
|
69
|
+
handlers.onDisconnected?.(reason !== undefined ? livekit_client_1.DisconnectReason[reason] : undefined);
|
|
70
|
+
});
|
|
71
|
+
room.on(livekit_client_1.RoomEvent.ParticipantConnected, (participant) => {
|
|
72
|
+
// Filter for agent participants (non-browser identities)
|
|
73
|
+
if (participant.identity !== "browser") {
|
|
74
|
+
handlers.onAgentConnected?.({
|
|
75
|
+
identity: participant.identity,
|
|
76
|
+
name: participant.name ?? participant.identity,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
room.on(livekit_client_1.RoomEvent.TrackSubscribed, (track, _publication, _participant) => {
|
|
81
|
+
// Auto-attach audio tracks so the user hears the agent
|
|
82
|
+
if (track.kind === livekit_client_1.Track.Kind.Audio) {
|
|
83
|
+
track.attach();
|
|
84
|
+
}
|
|
85
|
+
handlers.onTrackSubscribed?.({
|
|
86
|
+
kind: track.kind === livekit_client_1.Track.Kind.Audio ? "audio" : "video",
|
|
87
|
+
source: track.source?.toString() ?? "unknown",
|
|
88
|
+
attach: () => track.attach(),
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
room.on(livekit_client_1.RoomEvent.TrackUnsubscribed, (track, _publication, _participant) => {
|
|
92
|
+
track.detach();
|
|
93
|
+
handlers.onTrackUnsubscribed?.({
|
|
94
|
+
kind: track.kind === livekit_client_1.Track.Kind.Audio ? "audio" : "video",
|
|
95
|
+
source: track.source?.toString() ?? "unknown",
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
room.on(livekit_client_1.RoomEvent.LocalTrackUnpublished, (publication) => {
|
|
99
|
+
publication.track?.detach();
|
|
100
|
+
});
|
|
101
|
+
room.on(livekit_client_1.RoomEvent.Reconnecting, () => {
|
|
102
|
+
handlers.onReconnecting?.();
|
|
103
|
+
});
|
|
104
|
+
room.on(livekit_client_1.RoomEvent.Reconnected, () => {
|
|
105
|
+
handlers.onReconnected?.();
|
|
106
|
+
});
|
|
107
|
+
// ── Connect ──
|
|
108
|
+
try {
|
|
109
|
+
await room.prepareConnection(this.url, this.token);
|
|
110
|
+
await room.connect(this.url, this.token);
|
|
111
|
+
await room.localParticipant.setMicrophoneEnabled(true);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// Clean up on connection failure
|
|
115
|
+
try {
|
|
116
|
+
await room.disconnect();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Ignore cleanup errors
|
|
120
|
+
}
|
|
121
|
+
handlers.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
// ── Return VoiceConnection ──
|
|
125
|
+
const connection = {
|
|
126
|
+
async disconnect() {
|
|
127
|
+
await room.disconnect();
|
|
128
|
+
},
|
|
129
|
+
async mute() {
|
|
130
|
+
await room.localParticipant.setMicrophoneEnabled(false);
|
|
131
|
+
muted = true;
|
|
132
|
+
},
|
|
133
|
+
async unmute() {
|
|
134
|
+
await room.localParticipant.setMicrophoneEnabled(true);
|
|
135
|
+
muted = false;
|
|
136
|
+
},
|
|
137
|
+
isMuted() {
|
|
138
|
+
return muted;
|
|
139
|
+
},
|
|
140
|
+
get room() {
|
|
141
|
+
return room;
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
return connection;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.HappyRobotVoiceClient = HappyRobotVoiceClient;
|
|
148
|
+
//# sourceMappingURL=voice-client.js.map
|
package/voice-client.mjs
ADDED