@hainiva/agent-sdk 0.0.0-stage → 0.2.0
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/CHANGELOG.md +54 -0
- package/LICENSE +21 -0
- package/README.md +201 -2
- package/SECURITY.md +33 -0
- package/dist/cjs/agent.cjs +316 -0
- package/dist/cjs/agent.d.cts +235 -0
- package/dist/cjs/calls.cjs +277 -0
- package/dist/cjs/calls.d.cts +232 -0
- package/dist/cjs/contract.cjs +14 -0
- package/dist/cjs/contract.d.cts +215 -0
- package/dist/cjs/embed.cjs +11 -0
- package/dist/cjs/embed.d.cts +13 -0
- package/dist/cjs/emitter.cjs +50 -0
- package/dist/cjs/emitter.d.cts +22 -0
- package/dist/cjs/errors.cjs +28 -0
- package/dist/cjs/errors.d.cts +15 -0
- package/dist/cjs/events.cjs +97 -0
- package/dist/cjs/events.d.cts +97 -0
- package/dist/cjs/index.cjs +72 -0
- package/dist/cjs/index.d.cts +28 -0
- package/dist/cjs/livekit.cjs +56 -0
- package/dist/cjs/livekit.d.cts +35 -0
- package/dist/cjs/log.cjs +15 -0
- package/dist/cjs/log.d.cts +5 -0
- package/dist/cjs/react-native.cjs +27 -0
- package/dist/cjs/react-native.d.cts +38 -0
- package/dist/cjs/redact.cjs +71 -0
- package/dist/cjs/redact.d.cts +21 -0
- package/dist/cjs/rest.cjs +280 -0
- package/dist/cjs/rest.d.cts +166 -0
- package/dist/cjs/session.cjs +159 -0
- package/dist/cjs/session.d.cts +101 -0
- package/dist/cjs/singleFlight.cjs +49 -0
- package/dist/cjs/singleFlight.d.cts +32 -0
- package/dist/cjs/url.cjs +39 -0
- package/dist/cjs/url.d.cts +13 -0
- package/dist/cjs/web.cjs +28 -0
- package/dist/cjs/web.d.cts +23 -0
- package/dist/cjs/ws.cjs +246 -0
- package/dist/cjs/ws.d.cts +134 -0
- package/dist/esm/agent.d.ts +236 -0
- package/dist/esm/agent.d.ts.map +1 -0
- package/dist/esm/agent.js +313 -0
- package/dist/esm/agent.js.map +1 -0
- package/dist/esm/calls.d.ts +233 -0
- package/dist/esm/calls.d.ts.map +1 -0
- package/dist/esm/calls.js +271 -0
- package/dist/esm/calls.js.map +1 -0
- package/dist/esm/contract.d.ts +216 -0
- package/dist/esm/contract.d.ts.map +1 -0
- package/dist/esm/contract.js +12 -0
- package/dist/esm/contract.js.map +1 -0
- package/dist/esm/embed.d.ts +14 -0
- package/dist/esm/embed.d.ts.map +1 -0
- package/dist/esm/embed.js +9 -0
- package/dist/esm/embed.js.map +1 -0
- package/dist/esm/emitter.d.ts +23 -0
- package/dist/esm/emitter.d.ts.map +1 -0
- package/dist/esm/emitter.js +47 -0
- package/dist/esm/emitter.js.map +1 -0
- package/dist/esm/errors.d.ts +16 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +25 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/events.d.ts +98 -0
- package/dist/esm/events.d.ts.map +1 -0
- package/dist/esm/events.js +90 -0
- package/dist/esm/events.js.map +1 -0
- package/dist/esm/index.d.ts +29 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +29 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/livekit.d.ts +36 -0
- package/dist/esm/livekit.d.ts.map +1 -0
- package/dist/esm/livekit.js +54 -0
- package/dist/esm/livekit.js.map +1 -0
- package/dist/esm/log.d.ts +6 -0
- package/dist/esm/log.d.ts.map +1 -0
- package/dist/esm/log.js +13 -0
- package/dist/esm/log.js.map +1 -0
- package/dist/esm/react-native.d.ts +39 -0
- package/dist/esm/react-native.d.ts.map +1 -0
- package/dist/esm/react-native.js +23 -0
- package/dist/esm/react-native.js.map +1 -0
- package/dist/esm/redact.d.ts +22 -0
- package/dist/esm/redact.d.ts.map +1 -0
- package/dist/esm/redact.js +66 -0
- package/dist/esm/redact.js.map +1 -0
- package/dist/esm/rest.d.ts +167 -0
- package/dist/esm/rest.d.ts.map +1 -0
- package/dist/esm/rest.js +275 -0
- package/dist/esm/rest.js.map +1 -0
- package/dist/esm/session.d.ts +102 -0
- package/dist/esm/session.d.ts.map +1 -0
- package/dist/esm/session.js +155 -0
- package/dist/esm/session.js.map +1 -0
- package/dist/esm/singleFlight.d.ts +33 -0
- package/dist/esm/singleFlight.d.ts.map +1 -0
- package/dist/esm/singleFlight.js +46 -0
- package/dist/esm/singleFlight.js.map +1 -0
- package/dist/esm/url.d.ts +14 -0
- package/dist/esm/url.d.ts.map +1 -0
- package/dist/esm/url.js +37 -0
- package/dist/esm/url.js.map +1 -0
- package/dist/esm/web.d.ts +24 -0
- package/dist/esm/web.d.ts.map +1 -0
- package/dist/esm/web.js +23 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/esm/ws.d.ts +135 -0
- package/dist/esm/ws.d.ts.map +1 -0
- package/dist/esm/ws.js +242 -0
- package/dist/esm/ws.js.map +1 -0
- package/package.json +80 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC7I,OAAO,EACL,cAAc,EAAE,WAAW,EAC3B,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,GAC/H,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAAE,YAAY,EAChC,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,GACpG,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAClE,KAAK,IAAI,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAC5G,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,GACvI,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAChI,OAAO,EACL,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EACrD,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,GAC3J,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAC5E,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,GACnE,MAAM,aAAa,CAAC;AACrB,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hainiva/agent-sdk — build your own agent app on HAINIVA AICC: staff sign-in
|
|
3
|
+
* with your backend's assertion, the live event stream, and calls.
|
|
4
|
+
*
|
|
5
|
+
* Entry points:
|
|
6
|
+
* "@hainiva/agent-sdk" transport-agnostic core (this file) — no LiveKit, no DOM, no React Native
|
|
7
|
+
* "@hainiva/agent-sdk/web" localStorage store (opt-in), LiveKit call media
|
|
8
|
+
* "@hainiva/agent-sdk/react-native" secure-store session, LiveKit call media
|
|
9
|
+
* "@hainiva/agent-sdk/embed" the embeddable desk (not yet available)
|
|
10
|
+
*
|
|
11
|
+
* Start with HainivaAgent (./agent): it wires the session, the REST client,
|
|
12
|
+
* the event socket and the call state machine together. The parts are exported
|
|
13
|
+
* too, for apps that want their own wiring.
|
|
14
|
+
*/
|
|
15
|
+
export const SDK_VERSION = "0.2.0";
|
|
16
|
+
export { HainivaAgentError } from "./errors.js";
|
|
17
|
+
export { Redactor, redactString, redactValue } from "./redact.js";
|
|
18
|
+
export { safeLogger } from "./log.js";
|
|
19
|
+
export { assertSafeUrl } from "./url.js";
|
|
20
|
+
export { TypedEmitter } from "./emitter.js";
|
|
21
|
+
export { singleFlight, createTokenRefresher } from "./singleFlight.js";
|
|
22
|
+
export { SessionManager, memoryStore, } from "./session.js";
|
|
23
|
+
export { ReconnectingSocket, backoffDelay, } from "./ws.js";
|
|
24
|
+
export { CallStore, transition, activeCall, ringingCalls, initialCallsState, } from "./calls.js";
|
|
25
|
+
export { HainivaAgent } from "./agent.js";
|
|
26
|
+
export { AgentRestClient, errorFromResponse, newIdempotencyKey, } from "./rest.js";
|
|
27
|
+
export { AGENT_CLOSE_CODES, agentSocketBindings, isEventFrame, ringInfo, toCallEvents, } from "./events.js";
|
|
28
|
+
export * from "./contract.js";
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,UAAU,EAAe,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAwE,MAAM,mBAAmB,CAAC;AAC7I,OAAO,EACL,cAAc,EAAE,WAAW,GAE5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAAE,YAAY,GAEjC,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,GAGnE,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAwF,MAAM,YAAY,CAAC;AAChI,OAAO,EACL,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,GAEtD,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,GAE7E,MAAM,aAAa,CAAC;AACrB,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joining a call's LiveKit room. Used by the /web and /react-native entry points
|
|
3
|
+
* only: `livekit-client` is a peer dependency, and the core never imports it.
|
|
4
|
+
*/
|
|
5
|
+
import { Room, type RoomConnectOptions, type RoomOptions } from "livekit-client";
|
|
6
|
+
import { Redactor } from "./redact.js";
|
|
7
|
+
export interface MediaJoin {
|
|
8
|
+
/** wss:// LiveKit URL. */
|
|
9
|
+
url: string;
|
|
10
|
+
/** Room token for this call — kept out of every error. */
|
|
11
|
+
token: string;
|
|
12
|
+
}
|
|
13
|
+
export interface JoinOptions {
|
|
14
|
+
/** Start with the microphone on. Default true. */
|
|
15
|
+
microphone?: boolean;
|
|
16
|
+
roomOptions?: RoomOptions;
|
|
17
|
+
connectOptions?: RoomConnectOptions;
|
|
18
|
+
/** ws://localhost in development. Default false. */
|
|
19
|
+
allowInsecureLocalhost?: boolean;
|
|
20
|
+
redactor?: Redactor;
|
|
21
|
+
}
|
|
22
|
+
export interface MediaCall {
|
|
23
|
+
readonly room: Room;
|
|
24
|
+
setMuted(muted: boolean): Promise<void>;
|
|
25
|
+
/** Leave the room (idempotent). */
|
|
26
|
+
leave(): Promise<void>;
|
|
27
|
+
/** The room closed (far end hung up, server ended it, network lost). Returns an unsubscribe. */
|
|
28
|
+
onDisconnected(fn: () => void): () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Join with the call's media credentials, microphone on. The token is handed to
|
|
32
|
+
* LiveKit only; errors are redacted (LiveKit's own error text can contain its
|
|
33
|
+
* signalling URL, which carries the token).
|
|
34
|
+
*/
|
|
35
|
+
export declare function joinCallRoom(join: MediaJoin, o?: JoinOptions): Promise<MediaCall>;
|
|
36
|
+
//# sourceMappingURL=livekit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"livekit.d.ts","sourceRoot":"","sources":["../../src/livekit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAa,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG5F,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,oDAAoD;IACpD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,mCAAmC;IACnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,gGAAgG;IAChG,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC5C;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,GAAE,WAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CA+B3F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joining a call's LiveKit room. Used by the /web and /react-native entry points
|
|
3
|
+
* only: `livekit-client` is a peer dependency, and the core never imports it.
|
|
4
|
+
*/
|
|
5
|
+
import { Room, RoomEvent } from "livekit-client";
|
|
6
|
+
import { HainivaAgentError } from "./errors.js";
|
|
7
|
+
import { Redactor } from "./redact.js";
|
|
8
|
+
import { assertSafeUrl } from "./url.js";
|
|
9
|
+
/**
|
|
10
|
+
* Join with the call's media credentials, microphone on. The token is handed to
|
|
11
|
+
* LiveKit only; errors are redacted (LiveKit's own error text can contain its
|
|
12
|
+
* signalling URL, which carries the token).
|
|
13
|
+
*/
|
|
14
|
+
export async function joinCallRoom(join, o = {}) {
|
|
15
|
+
const redactor = o.redactor ?? new Redactor();
|
|
16
|
+
redactor.add(join.token);
|
|
17
|
+
assertSafeUrl(join.url, { kind: "ws", ...(o.allowInsecureLocalhost ? { allowInsecureLocalhost: true } : {}) });
|
|
18
|
+
if (!join.token)
|
|
19
|
+
throw new HainivaAgentError(0, "no_media_token");
|
|
20
|
+
const room = new Room(o.roomOptions);
|
|
21
|
+
try {
|
|
22
|
+
await room.connect(join.url, join.token, { autoSubscribe: true, ...o.connectOptions });
|
|
23
|
+
if (o.microphone !== false)
|
|
24
|
+
await room.localParticipant.setMicrophoneEnabled(true);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
await room.disconnect().catch(() => undefined);
|
|
28
|
+
throw HainivaAgentError.from(e, "media_connect_failed", redactor);
|
|
29
|
+
}
|
|
30
|
+
let left = false;
|
|
31
|
+
return {
|
|
32
|
+
room,
|
|
33
|
+
async setMuted(muted) {
|
|
34
|
+
try {
|
|
35
|
+
await room.localParticipant.setMicrophoneEnabled(!muted);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
throw HainivaAgentError.from(e, "media_mute_failed", redactor);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async leave() {
|
|
42
|
+
if (left)
|
|
43
|
+
return;
|
|
44
|
+
left = true;
|
|
45
|
+
await room.disconnect().catch(() => undefined);
|
|
46
|
+
},
|
|
47
|
+
onDisconnected(fn) {
|
|
48
|
+
const h = () => fn();
|
|
49
|
+
room.on(RoomEvent.Disconnected, h);
|
|
50
|
+
return () => { room.off(RoomEvent.Disconnected, h); };
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=livekit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"livekit.js","sourceRoot":"","sources":["../../src/livekit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,IAAI,EAAE,SAAS,EAA6C,MAAM,gBAAgB,CAAC;AAE5F,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AA4BzC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAe,EAAE,IAAiB,EAAE;IACrE,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,QAAQ,EAAE,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,iBAAiB,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;QACvF,IAAI,CAAC,CAAC,UAAU,KAAK,KAAK;YAAE,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,sBAAsB,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,QAAQ,CAAC,KAAK;YAClB,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC;YACjE,OAAO,CAAC,EAAE,CAAC;gBAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;YAAC,CAAC;QAC/E,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,IAAI;gBAAE,OAAO;YACjB,IAAI,GAAG,IAAI,CAAC;YACZ,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjD,CAAC;QACD,cAAc,CAAC,EAAE;YACf,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YACnC,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Redactor } from "./redact.js";
|
|
2
|
+
/** The partner's logger. The SDK logs nothing unless one is given. */
|
|
3
|
+
export type Logger = (event: string, detail?: unknown) => void;
|
|
4
|
+
/** A logger that redacts every detail before the partner's logger sees it. */
|
|
5
|
+
export declare function safeLogger(log: Logger | undefined, redactor?: Redactor): Logger;
|
|
6
|
+
//# sourceMappingURL=log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,sEAAsE;AACtE,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE/D,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,GAAE,QAAyB,GAAG,MAAM,CAO/F"}
|
package/dist/esm/log.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Redactor } from "./redact.js";
|
|
2
|
+
/** A logger that redacts every detail before the partner's logger sees it. */
|
|
3
|
+
export function safeLogger(log, redactor = new Redactor()) {
|
|
4
|
+
if (!log)
|
|
5
|
+
return () => { };
|
|
6
|
+
return (event, detail) => {
|
|
7
|
+
try {
|
|
8
|
+
log(redactor.string(event), detail === undefined ? undefined : redactor.value(detail));
|
|
9
|
+
}
|
|
10
|
+
catch { /* a broken logger must not break a call */ }
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKvC,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,GAAuB,EAAE,WAAqB,IAAI,QAAQ,EAAE;IACrF,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACzF,CAAC;QAAC,MAAM,CAAC,CAAC,2CAA2C,CAAC,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hainiva/agent-sdk/react-native — React Native adapters: the session in the
|
|
3
|
+
* Keychain / Android Keystore (expo-secure-store) and LiveKit call media.
|
|
4
|
+
*
|
|
5
|
+
* Call `registerGlobals()` from `@livekit/react-native` once at startup before
|
|
6
|
+
* joining a room. Native ringing (CallKit / Android call notification) is
|
|
7
|
+
* `@hainiva/react-native-call`.
|
|
8
|
+
*/
|
|
9
|
+
import type { SessionStore } from "./session.js";
|
|
10
|
+
export { joinCallRoom, type JoinOptions, type MediaCall, type MediaJoin } from "./livekit.js";
|
|
11
|
+
/** The part of `expo-secure-store` this adapter uses: pass the module itself. */
|
|
12
|
+
export interface SecureStoreModule {
|
|
13
|
+
getItemAsync(key: string, options?: Record<string, unknown>): Promise<string | null>;
|
|
14
|
+
setItemAsync(key: string, value: string, options?: Record<string, unknown>): Promise<void>;
|
|
15
|
+
deleteItemAsync(key: string, options?: Record<string, unknown>): Promise<void>;
|
|
16
|
+
/** expo-secure-store's constant; used as the default accessibility. */
|
|
17
|
+
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface SecureStoreSessionOptions {
|
|
20
|
+
/** Default "hainiva.agent.session". Letters, digits, ".", "-" and "_" only. */
|
|
21
|
+
key?: string;
|
|
22
|
+
/**
|
|
23
|
+
* iPhone Keychain accessibility. Default AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY:
|
|
24
|
+
* readable while the phone is locked (a call that wakes the app must find the
|
|
25
|
+
* session) and never migrated to another device.
|
|
26
|
+
*/
|
|
27
|
+
keychainAccessible?: unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The session (and so the refresh token) in secure storage only. There is
|
|
31
|
+
* deliberately no fallback to AsyncStorage or another plain store: if secure
|
|
32
|
+
* storage fails, the session stays in memory and the next launch signs in again
|
|
33
|
+
* with a fresh assertion.
|
|
34
|
+
*
|
|
35
|
+
* import * as SecureStore from "expo-secure-store";
|
|
36
|
+
* const store = secureStoreSessionStore(SecureStore);
|
|
37
|
+
*/
|
|
38
|
+
export declare function secureStoreSessionStore(secure: SecureStoreModule, o?: SecureStoreSessionOptions): SessionStore;
|
|
39
|
+
//# sourceMappingURL=react-native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../../src/react-native.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9F,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACrF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,uEAAuE;IACvE,mCAAmC,CAAC,EAAE,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,GAAE,yBAA8B,GAAG,YAAY,CAUlH"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { joinCallRoom } from "./livekit.js";
|
|
2
|
+
/**
|
|
3
|
+
* The session (and so the refresh token) in secure storage only. There is
|
|
4
|
+
* deliberately no fallback to AsyncStorage or another plain store: if secure
|
|
5
|
+
* storage fails, the session stays in memory and the next launch signs in again
|
|
6
|
+
* with a fresh assertion.
|
|
7
|
+
*
|
|
8
|
+
* import * as SecureStore from "expo-secure-store";
|
|
9
|
+
* const store = secureStoreSessionStore(SecureStore);
|
|
10
|
+
*/
|
|
11
|
+
export function secureStoreSessionStore(secure, o = {}) {
|
|
12
|
+
const key = o.key ?? "hainiva.agent.session";
|
|
13
|
+
if (!/^[A-Za-z0-9._-]+$/.test(key))
|
|
14
|
+
throw new Error("secureStoreSessionStore: key may use only letters, digits, '.', '-' and '_'");
|
|
15
|
+
const access = o.keychainAccessible ?? secure.AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY;
|
|
16
|
+
const opts = access === undefined ? {} : { keychainAccessible: access };
|
|
17
|
+
return {
|
|
18
|
+
get: () => secure.getItemAsync(key, opts),
|
|
19
|
+
set: (v) => secure.setItemAsync(key, v, opts),
|
|
20
|
+
remove: () => secure.deleteItemAsync(key, opts),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=react-native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-native.js","sourceRoot":"","sources":["../../src/react-native.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAoD,MAAM,cAAc,CAAC;AAsB9F;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAyB,EAAE,IAA+B,EAAE;IAClG,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,uBAAuB,CAAC;IAC7C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACnI,MAAM,MAAM,GAAG,CAAC,CAAC,kBAAkB,IAAI,MAAM,CAAC,mCAAmC,CAAC;IAClF,MAAM,IAAI,GAA4B,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IACjG,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC;QACzC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC;QAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC;KAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction: no token, assertion or secret may leave the SDK in an error message,
|
|
3
|
+
* a log line or an event. Two layers:
|
|
4
|
+
* - patterns that catch credentials by shape (JWTs, Bearer headers, token query
|
|
5
|
+
* parameters, HAINIVA key prefixes), always on;
|
|
6
|
+
* - a Redactor that also knows the exact secrets this client holds right now
|
|
7
|
+
* (the current access and refresh tokens), so even an opaque token is caught.
|
|
8
|
+
*/
|
|
9
|
+
/** Redact credential-shaped substrings. */
|
|
10
|
+
export declare function redactString(s: string, known?: Iterable<string>): string;
|
|
11
|
+
/** A deep copy with credentials removed: sensitive keys blanked, strings scrubbed, Errors flattened. */
|
|
12
|
+
export declare function redactValue(v: unknown, known?: Iterable<string>, depth?: number): unknown;
|
|
13
|
+
/** Knows the secrets one client holds right now, on top of the patterns. */
|
|
14
|
+
export declare class Redactor {
|
|
15
|
+
private readonly secrets;
|
|
16
|
+
add(...secrets: (string | null | undefined)[]): void;
|
|
17
|
+
remove(...secrets: (string | null | undefined)[]): void;
|
|
18
|
+
clear(): void;
|
|
19
|
+
string(s: string): string;
|
|
20
|
+
value(v: unknown): unknown;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAM,GAAG,MAAM,CAK5E;AAED,wGAAwG;AACxG,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAcxF;AAED,4EAA4E;AAC5E,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI;IACpD,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI;IACvD,KAAK,IAAI,IAAI;IACb,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IACzB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO;CAC3B"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction: no token, assertion or secret may leave the SDK in an error message,
|
|
3
|
+
* a log line or an event. Two layers:
|
|
4
|
+
* - patterns that catch credentials by shape (JWTs, Bearer headers, token query
|
|
5
|
+
* parameters, HAINIVA key prefixes), always on;
|
|
6
|
+
* - a Redactor that also knows the exact secrets this client holds right now
|
|
7
|
+
* (the current access and refresh tokens), so even an opaque token is caught.
|
|
8
|
+
*/
|
|
9
|
+
const PATTERNS = [
|
|
10
|
+
// JWT / JWS / JWE (assertions, access tokens, LiveKit tokens).
|
|
11
|
+
[/eyJ[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}(?:\.[A-Za-z0-9_-]*){1,3}/g, "[redacted-jwt]"],
|
|
12
|
+
// Authorization header values.
|
|
13
|
+
[/\b(Bearer|Basic|Token)\s+[A-Za-z0-9._~+/=-]{8,}/gi, "$1 [redacted]"],
|
|
14
|
+
// Credentials in a query string.
|
|
15
|
+
[/([?&#](?:access_token|refresh_token|id_token|token|assertion|ticket|api_key|apikey|key|secret|signature|sig|password)=)[^&#\s"']+/gi, "$1[redacted]"],
|
|
16
|
+
// HAINIVA API keys and refresh tokens by prefix.
|
|
17
|
+
[/\b(aicc_(?:live|test)_|hnv_|agr_|apr_)[A-Za-z0-9_-]{6,}/g, "$1[redacted]"],
|
|
18
|
+
];
|
|
19
|
+
/** Object keys whose values are never shown. */
|
|
20
|
+
const SENSITIVE_KEY = /token|assertion|secret|password|passwd|authori[sz]ation|cookie|refresh|jwt|signature|api[-_]?key|private[-_]?key|credential/i;
|
|
21
|
+
/** Redact credential-shaped substrings. */
|
|
22
|
+
export function redactString(s, known = []) {
|
|
23
|
+
let out = s;
|
|
24
|
+
for (const k of known)
|
|
25
|
+
if (k && k.length >= 8)
|
|
26
|
+
out = out.split(k).join("[redacted]");
|
|
27
|
+
for (const [re, by] of PATTERNS)
|
|
28
|
+
out = out.replace(re, by);
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
/** A deep copy with credentials removed: sensitive keys blanked, strings scrubbed, Errors flattened. */
|
|
32
|
+
export function redactValue(v, known = [], depth = 0) {
|
|
33
|
+
const list = [...known];
|
|
34
|
+
if (typeof v === "string")
|
|
35
|
+
return redactString(v, list);
|
|
36
|
+
if (v === null || typeof v !== "object")
|
|
37
|
+
return v;
|
|
38
|
+
if (depth > 6)
|
|
39
|
+
return "[truncated]";
|
|
40
|
+
if (v instanceof Error) {
|
|
41
|
+
return { name: v.name, message: redactString(v.message, list), ...(v.stack ? { stack: redactString(v.stack, list) } : {}) };
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(v))
|
|
44
|
+
return v.slice(0, 100).map((x) => redactValue(x, list, depth + 1));
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const [k, x] of Object.entries(v)) {
|
|
47
|
+
out[k] = SENSITIVE_KEY.test(k) && x !== null && x !== undefined && x !== "" ? "[redacted]" : redactValue(x, list, depth + 1);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
/** Knows the secrets one client holds right now, on top of the patterns. */
|
|
52
|
+
export class Redactor {
|
|
53
|
+
constructor() {
|
|
54
|
+
this.secrets = new Set();
|
|
55
|
+
}
|
|
56
|
+
add(...secrets) { for (const s of secrets)
|
|
57
|
+
if (s)
|
|
58
|
+
this.secrets.add(s); }
|
|
59
|
+
remove(...secrets) { for (const s of secrets)
|
|
60
|
+
if (s)
|
|
61
|
+
this.secrets.delete(s); }
|
|
62
|
+
clear() { this.secrets.clear(); }
|
|
63
|
+
string(s) { return redactString(s, this.secrets); }
|
|
64
|
+
value(v) { return redactValue(v, this.secrets); }
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/redact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The REST client for the Agent API (`/agent/v1/*`).
|
|
3
|
+
*
|
|
4
|
+
* - `baseUrl` is checked with assertSafeUrl (HTTPS only, no credential in it);
|
|
5
|
+
* - the access token goes in the Authorization header only — never in a URL;
|
|
6
|
+
* - a 401 `token_expired` (or `token_invalid`) refreshes ONCE (single flight
|
|
7
|
+
* across every caller: SessionManager) and retries the request once; a
|
|
8
|
+
* refused refresh signs in again with a NEW assertion from `getAssertion`;
|
|
9
|
+
* a 401 `session_revoked` is final (the facade emits `revoked`);
|
|
10
|
+
* - every POST carries an `Idempotency-Key` (the retry after a refresh reuses
|
|
11
|
+
* it, so the server never does the action twice);
|
|
12
|
+
* - each request has a timeout (default 15 s) and honours an AbortSignal;
|
|
13
|
+
* - any non-2xx becomes a HainivaAgentError {status, code, body} from the
|
|
14
|
+
* server's `{error:{code,message}}` envelope, redacted; non-JSON or
|
|
15
|
+
* non-object bodies are handled defensively.
|
|
16
|
+
*/
|
|
17
|
+
import type { AgentAcceptDto, AgentCallDto, AgentConversationDto, AgentDispositionDto, AgentMeDto, AgentMediaTokenDto, AgentMessageDto, AgentPage, AgentPresenceStatus, AgentPushSubscriptionDto, AgentPushSubscriptionInput, AgentRingDto, AgentSessionDto, SupervisorAgentDto, SupervisorLiveCallDto, SupervisorSuperviseDto } from "./contract.js";
|
|
18
|
+
import { HainivaAgentError } from "./errors.js";
|
|
19
|
+
import { type Logger } from "./log.js";
|
|
20
|
+
import { Redactor } from "./redact.js";
|
|
21
|
+
import type { AgentSession, SessionTransport } from "./session.js";
|
|
22
|
+
export interface AgentRestOptions {
|
|
23
|
+
/** e.g. https://api.hainiva.com (HTTPS only). */
|
|
24
|
+
baseUrl: string;
|
|
25
|
+
/** Your HAINIVA organisation id: sign-in and refresh name it. */
|
|
26
|
+
tenantId: string;
|
|
27
|
+
fetch?: typeof fetch;
|
|
28
|
+
/** Per request, default 15 000 ms. */
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
/** Local development only: http://localhost. */
|
|
31
|
+
allowInsecureLocalhost?: boolean;
|
|
32
|
+
/** Device shown to the organisation's admins in the session list. */
|
|
33
|
+
device?: {
|
|
34
|
+
label?: string;
|
|
35
|
+
platform?: "ios" | "android" | "web" | "other";
|
|
36
|
+
};
|
|
37
|
+
redactor?: Redactor;
|
|
38
|
+
log?: Logger;
|
|
39
|
+
}
|
|
40
|
+
/** Where the client gets its access token, and how it reports a refused one. */
|
|
41
|
+
export interface TokenSource {
|
|
42
|
+
accessToken(): Promise<string>;
|
|
43
|
+
/** The server refused this token: refresh before the next request. */
|
|
44
|
+
invalidate(refused?: string): void;
|
|
45
|
+
}
|
|
46
|
+
export interface RequestOptions {
|
|
47
|
+
body?: unknown;
|
|
48
|
+
query?: Record<string, string | number | undefined>;
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
/** Overrides the client's timeout for this request. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
}
|
|
53
|
+
/** LiveKit room credentials for a call. */
|
|
54
|
+
export type MediaCredentials = AgentMediaTokenDto;
|
|
55
|
+
export type AgentStatus = AgentPresenceStatus;
|
|
56
|
+
/** Where a call is transferred. */
|
|
57
|
+
export type CallTransferTarget = {
|
|
58
|
+
agentId: string;
|
|
59
|
+
mode?: "warm" | "blind";
|
|
60
|
+
} | {
|
|
61
|
+
queueId: string;
|
|
62
|
+
} | {
|
|
63
|
+
number: string;
|
|
64
|
+
mode?: "warm" | "blind";
|
|
65
|
+
};
|
|
66
|
+
export interface ConversationListQuery {
|
|
67
|
+
scope?: "all" | "mine";
|
|
68
|
+
status?: "open" | "closed" | "all";
|
|
69
|
+
cursor?: string;
|
|
70
|
+
limit?: number;
|
|
71
|
+
}
|
|
72
|
+
/** A random UUID v4: crypto.randomUUID where it exists (browsers, Node), else getRandomValues, else Math.random (Idempotency-Key only, not a secret). */
|
|
73
|
+
export declare function newIdempotencyKey(): string;
|
|
74
|
+
/** Pure: the error a non-2xx answer becomes. Exported for tests. */
|
|
75
|
+
export declare function errorFromResponse(status: number, data: unknown, redactor?: Redactor, retryAfter?: string | null): HainivaAgentError;
|
|
76
|
+
/**
|
|
77
|
+
* The Agent API over fetch. `tokens` is normally the SessionManager; the
|
|
78
|
+
* client's own `sessions` transport is what that SessionManager signs in with.
|
|
79
|
+
*/
|
|
80
|
+
export declare class AgentRestClient {
|
|
81
|
+
private readonly o;
|
|
82
|
+
readonly baseUrl: string;
|
|
83
|
+
private readonly fetchFn;
|
|
84
|
+
private readonly timeoutMs;
|
|
85
|
+
private readonly redactor;
|
|
86
|
+
private readonly log;
|
|
87
|
+
private tokens;
|
|
88
|
+
constructor(o: AgentRestOptions, tokens?: TokenSource);
|
|
89
|
+
/** Attach the token source after construction (the SessionManager needs `sessions` first). */
|
|
90
|
+
useTokens(tokens: TokenSource): void;
|
|
91
|
+
/** The wss:// URL of the event stream, derived from baseUrl (never from a server answer). */
|
|
92
|
+
get wsUrl(): string;
|
|
93
|
+
readonly sessions: SessionTransport<AgentSession & AgentSessionDto>;
|
|
94
|
+
/** An authenticated request: refresh-and-retry once on an expired token. */
|
|
95
|
+
request<T>(method: "GET" | "POST" | "PUT" | "DELETE", path: string, opts?: RequestOptions): Promise<T>;
|
|
96
|
+
private raw;
|
|
97
|
+
me(o?: RequestOptions): Promise<AgentMeDto>;
|
|
98
|
+
setStatus(status: AgentStatus, o?: RequestOptions): Promise<{
|
|
99
|
+
status: AgentStatus;
|
|
100
|
+
}>;
|
|
101
|
+
/** Rings for this member now (after a cold start, a missed push or a resync). */
|
|
102
|
+
pendingRings(o?: RequestOptions): Promise<AgentRingDto[]>;
|
|
103
|
+
getCall(callId: string, o?: RequestOptions): Promise<AgentCallDto>;
|
|
104
|
+
acceptCall(callId: string, o?: RequestOptions): Promise<AgentAcceptDto>;
|
|
105
|
+
declineCall(callId: string, o?: RequestOptions): Promise<{
|
|
106
|
+
callId: string;
|
|
107
|
+
declined: true;
|
|
108
|
+
}>;
|
|
109
|
+
endCall(callId: string, o?: RequestOptions): Promise<{
|
|
110
|
+
callId: string;
|
|
111
|
+
ended: true;
|
|
112
|
+
}>;
|
|
113
|
+
holdCall(callId: string, on: boolean, o?: RequestOptions): Promise<{
|
|
114
|
+
callId: string;
|
|
115
|
+
onHold: boolean;
|
|
116
|
+
}>;
|
|
117
|
+
transferCall(callId: string, target: CallTransferTarget, o?: RequestOptions): Promise<{
|
|
118
|
+
callId: string;
|
|
119
|
+
transferred: true;
|
|
120
|
+
}>;
|
|
121
|
+
/** Re-mint the LiveKit token while still a participant (reconnect, token near expiry). */
|
|
122
|
+
mediaToken(callId: string, o?: RequestOptions): Promise<MediaCredentials>;
|
|
123
|
+
dispositions(channel?: string, o?: RequestOptions): Promise<AgentDispositionDto[]>;
|
|
124
|
+
wrapUp(callId: string, w?: {
|
|
125
|
+
dispositionCode?: string;
|
|
126
|
+
notes?: string;
|
|
127
|
+
}, o?: RequestOptions): Promise<{
|
|
128
|
+
callId: string;
|
|
129
|
+
wrappedUp: true;
|
|
130
|
+
}>;
|
|
131
|
+
listConversations(q?: ConversationListQuery, o?: RequestOptions): Promise<AgentPage<AgentConversationDto>>;
|
|
132
|
+
getConversation(conversationId: string, o?: RequestOptions): Promise<AgentConversationDto>;
|
|
133
|
+
/** Claim it (no agentId), or — a supervisor — assign it to a colleague. */
|
|
134
|
+
assignConversation(conversationId: string, agentId?: string, o?: RequestOptions): Promise<unknown>;
|
|
135
|
+
releaseConversation(conversationId: string, note?: string, o?: RequestOptions): Promise<{
|
|
136
|
+
conversationId: string;
|
|
137
|
+
released: true;
|
|
138
|
+
}>;
|
|
139
|
+
transferConversation(conversationId: string, to: {
|
|
140
|
+
agentId: string;
|
|
141
|
+
} | {
|
|
142
|
+
queueId: string;
|
|
143
|
+
note?: string;
|
|
144
|
+
}, o?: RequestOptions): Promise<unknown>;
|
|
145
|
+
closeConversation(conversationId: string, o?: RequestOptions): Promise<{
|
|
146
|
+
conversationId: string;
|
|
147
|
+
closed: true;
|
|
148
|
+
}>;
|
|
149
|
+
listMessages(conversationId: string, q?: {
|
|
150
|
+
after?: string;
|
|
151
|
+
limit?: number;
|
|
152
|
+
}, o?: RequestOptions): Promise<AgentPage<AgentMessageDto>>;
|
|
153
|
+
sendMessage(conversationId: string, text: string, o?: RequestOptions): Promise<Pick<AgentMessageDto, "id" | "conversationId" | "interactionId" | "createdAt">>;
|
|
154
|
+
typing(conversationId: string, o?: RequestOptions): Promise<{
|
|
155
|
+
ok: true;
|
|
156
|
+
}>;
|
|
157
|
+
liveCalls(o?: RequestOptions): Promise<SupervisorLiveCallDto[]>;
|
|
158
|
+
teamAgents(o?: RequestOptions): Promise<SupervisorAgentDto[]>;
|
|
159
|
+
supervise(callId: string, mode?: "monitor" | "whisper" | "barge", o?: RequestOptions): Promise<SupervisorSuperviseDto>;
|
|
160
|
+
setSuperviseMode(callId: string, mode: "monitor" | "whisper" | "barge", supervisorTrackSid?: string, o?: RequestOptions): Promise<{
|
|
161
|
+
callId: string;
|
|
162
|
+
mode: string;
|
|
163
|
+
}>;
|
|
164
|
+
registerPush(sub: AgentPushSubscriptionInput, o?: RequestOptions): Promise<AgentPushSubscriptionDto>;
|
|
165
|
+
unregisterPush(token: string, o?: RequestOptions): Promise<void>;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=rest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/rest.ts"],"names":[],"mappings":"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"}
|