@m4trix/core 0.5.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/README.md +72 -0
- package/dist/api/index.cjs +83 -0
- package/dist/api/index.cjs.map +1 -0
- package/dist/api/index.d.cts +74 -0
- package/dist/api/index.d.ts +74 -0
- package/dist/api/index.js +81 -0
- package/dist/api/index.js.map +1 -0
- package/dist/helper/index.cjs +253 -0
- package/dist/helper/index.cjs.map +1 -0
- package/dist/helper/index.d.cts +92 -0
- package/dist/helper/index.d.ts +92 -0
- package/dist/helper/index.js +251 -0
- package/dist/helper/index.js.map +1 -0
- package/dist/index.cjs +2670 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +2656 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +1324 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +213 -0
- package/dist/react/index.d.ts +213 -0
- package/dist/react/index.js +1316 -0
- package/dist/react/index.js.map +1 -0
- package/dist/stream/index.cjs +716 -0
- package/dist/stream/index.cjs.map +1 -0
- package/dist/stream/index.d.cts +304 -0
- package/dist/stream/index.d.ts +304 -0
- package/dist/stream/index.js +712 -0
- package/dist/stream/index.js.map +1 -0
- package/dist/ui/index.cjs +316 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.cts +30 -0
- package/dist/ui/index.d.ts +30 -0
- package/dist/ui/index.js +314 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +123 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
[](https://dl.circleci.com/status-badge/redirect/gh/Pascal-Lohscheidt/build-ai/tree/main)
|
|
3
|
+
|
|
4
|
+
# @m4trix/core
|
|
5
|
+
|
|
6
|
+
A powerful TypeScript library for building AI-driven web applications. This package provides modular entry points like `@m4trix/core`, `@m4trix/core/ui`, and `@m4trix/core/stream`.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ๐ TypeScript-first approach
|
|
11
|
+
- ๐ฆ Tree-shaking support
|
|
12
|
+
- ๐จ Visual components for AI applications
|
|
13
|
+
- ๐งช Comprehensive test coverage
|
|
14
|
+
- ๐ Full TypeScript documentation
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// Coming soon
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Contributing
|
|
23
|
+
|
|
24
|
+
We welcome contributions! Please follow these guidelines:
|
|
25
|
+
|
|
26
|
+
1. Fork the repository
|
|
27
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
28
|
+
3. Make your changes following our commit conventions (see below)
|
|
29
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
30
|
+
5. Open a Pull Request
|
|
31
|
+
|
|
32
|
+
### Commit Conventions
|
|
33
|
+
|
|
34
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/) for our commit messages. This helps us maintain a clean and consistent git history.
|
|
35
|
+
|
|
36
|
+
Format:
|
|
37
|
+
```
|
|
38
|
+
<type>(<scope>): <description>
|
|
39
|
+
|
|
40
|
+
[optional body]
|
|
41
|
+
|
|
42
|
+
[optional footer(s)]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Types:
|
|
46
|
+
- `feat`: A new feature
|
|
47
|
+
- `fix`: A bug fix
|
|
48
|
+
- `docs`: Documentation only changes
|
|
49
|
+
- `style`: Changes that do not affect the meaning of the code
|
|
50
|
+
- `refactor`: A code change that neither fixes a bug nor adds a feature
|
|
51
|
+
- `perf`: A code change that improves performance
|
|
52
|
+
- `test`: Adding missing tests or correcting existing tests
|
|
53
|
+
- `chore`: Changes to the build process or auxiliary tools
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
```
|
|
57
|
+
feat(auth): add OAuth2 authentication
|
|
58
|
+
|
|
59
|
+
- Add Google OAuth2 provider
|
|
60
|
+
- Implement token refresh flow
|
|
61
|
+
- Add user profile endpoint
|
|
62
|
+
|
|
63
|
+
Closes #123
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
Created by the makers of [Stepsailor](https://stepsailor.com) (Pascal Lohscheidt)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/api/socket-handler/SocketIoFactory.ts
|
|
4
|
+
var SocketIoFactory = class _SocketIoFactory {
|
|
5
|
+
constructor(socket, prefix, hooks) {
|
|
6
|
+
this.socket = socket;
|
|
7
|
+
this.prefix = prefix;
|
|
8
|
+
this.hooks = hooks;
|
|
9
|
+
}
|
|
10
|
+
static setupSocketHandlers({
|
|
11
|
+
enableVoiceEvents,
|
|
12
|
+
enableChatEvents,
|
|
13
|
+
enableTranscriptEvents,
|
|
14
|
+
prefix = "",
|
|
15
|
+
socket,
|
|
16
|
+
hooks
|
|
17
|
+
}) {
|
|
18
|
+
const factory = new _SocketIoFactory(socket, prefix, hooks);
|
|
19
|
+
if (enableVoiceEvents) {
|
|
20
|
+
factory.setupVoiceEvents();
|
|
21
|
+
}
|
|
22
|
+
if (enableChatEvents) {
|
|
23
|
+
factory.setupChatEvents(socket);
|
|
24
|
+
}
|
|
25
|
+
if (enableTranscriptEvents) {
|
|
26
|
+
factory.setupTranscriptEvents(socket);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
setupVoiceEvents() {
|
|
30
|
+
const {
|
|
31
|
+
onVoiceInputFile,
|
|
32
|
+
onVoiceInputChunk,
|
|
33
|
+
onVoiceInputCommit,
|
|
34
|
+
onVoiceOutputDelta,
|
|
35
|
+
onVoiceOutputCommit,
|
|
36
|
+
onVoiceOutputFile,
|
|
37
|
+
onVoiceOutputTranscriptDelta,
|
|
38
|
+
onVoiceOutputTranscriptFull
|
|
39
|
+
} = this.hooks;
|
|
40
|
+
const prefix = this.prefixEvent;
|
|
41
|
+
if (onVoiceInputFile) {
|
|
42
|
+
this.socket.on(prefix("voice:input_file"), onVoiceInputFile);
|
|
43
|
+
}
|
|
44
|
+
if (onVoiceInputChunk) {
|
|
45
|
+
this.socket.on(prefix("voice:input_chunk"), onVoiceInputChunk);
|
|
46
|
+
}
|
|
47
|
+
if (onVoiceInputCommit) {
|
|
48
|
+
this.socket.on(prefix("voice:input_commit"), onVoiceInputCommit);
|
|
49
|
+
}
|
|
50
|
+
if (onVoiceOutputDelta) {
|
|
51
|
+
this.socket.on(prefix("voice:output_delta"), onVoiceOutputDelta);
|
|
52
|
+
}
|
|
53
|
+
if (onVoiceOutputCommit) {
|
|
54
|
+
this.socket.on(prefix("voice:output_commit"), onVoiceOutputCommit);
|
|
55
|
+
}
|
|
56
|
+
if (onVoiceOutputFile) {
|
|
57
|
+
this.socket.on(prefix("voice:output_file"), onVoiceOutputFile);
|
|
58
|
+
}
|
|
59
|
+
if (onVoiceOutputTranscriptDelta) {
|
|
60
|
+
this.socket.on(
|
|
61
|
+
prefix("voice:output_transcript_delta"),
|
|
62
|
+
onVoiceOutputTranscriptDelta
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (onVoiceOutputTranscriptFull) {
|
|
66
|
+
this.socket.on(
|
|
67
|
+
prefix("voice:output_transcript_full"),
|
|
68
|
+
onVoiceOutputTranscriptFull
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
setupChatEvents(_socket) {
|
|
73
|
+
}
|
|
74
|
+
setupTranscriptEvents(_socket) {
|
|
75
|
+
}
|
|
76
|
+
prefixEvent(event) {
|
|
77
|
+
return this.prefix ? `${this.prefix}:${event}` : event;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
exports.SocketIoFactory = SocketIoFactory;
|
|
82
|
+
//# sourceMappingURL=out.js.map
|
|
83
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/api/socket-handler/SocketIoFactory.ts"],"names":[],"mappings":";AAGO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EAKnB,YAAY,QAAgB,QAAgB,OAAsB;AACxE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,OAAO,oBAAoB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF,GAKS;AAGP,UAAM,UAAU,IAAI,iBAAgB,QAAQ,QAAQ,KAAM;AAC1D,QAAI,mBAAmB;AACrB,cAAQ,iBAAiB;AAAA,IAC3B;AAEA,QAAI,kBAAkB;AACpB,cAAQ,gBAAgB,MAAM;AAAA,IAChC;AAEA,QAAI,wBAAwB;AAC1B,cAAQ,sBAAsB,MAAM;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK;AAET,UAAM,SAAS,KAAK;AAEpB,QAAI,kBAAkB;AACpB,WAAK,OAAO,GAAG,OAAO,kBAAkB,GAAG,gBAAgB;AAAA,IAC7D;AAEA,QAAI,mBAAmB;AACrB,WAAK,OAAO,GAAG,OAAO,mBAAmB,GAAG,iBAAiB;AAAA,IAC/D;AAEA,QAAI,oBAAoB;AACtB,WAAK,OAAO,GAAG,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,IACjE;AAEA,QAAI,oBAAoB;AACtB,WAAK,OAAO,GAAG,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,IACjE;AAEA,QAAI,qBAAqB;AACvB,WAAK,OAAO,GAAG,OAAO,qBAAqB,GAAG,mBAAmB;AAAA,IACnE;AAEA,QAAI,mBAAmB;AACrB,WAAK,OAAO,GAAG,OAAO,mBAAmB,GAAG,iBAAiB;AAAA,IAC/D;AAEA,QAAI,8BAA8B;AAChC,WAAK,OAAO;AAAA,QACV,OAAO,+BAA+B;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,6BAA6B;AAC/B,WAAK,OAAO;AAAA,QACV,OAAO,8BAA8B;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAAuB;AAAA,EAE/C;AAAA,EAEQ,sBAAsB,SAAuB;AAAA,EAErD;AAAA,EAEQ,YAAY,OAAuB;AACzC,WAAO,KAAK,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EACnD;AACF","sourcesContent":["import { Socket } from 'socket.io';\nimport { Hooks, SetupSocketHandlersParams } from './socket-factory-types';\n\nexport class SocketIoFactory {\n private socket: Socket;\n private prefix: string;\n private hooks: Hooks<Socket>;\n\n private constructor(socket: Socket, prefix: string, hooks: Hooks<Socket>) {\n this.socket = socket;\n this.prefix = prefix;\n this.hooks = hooks;\n }\n\n static setupSocketHandlers({\n enableVoiceEvents,\n enableChatEvents,\n enableTranscriptEvents,\n prefix = '',\n socket,\n hooks,\n }: SetupSocketHandlersParams<\n Socket,\n {\n socket: Socket;\n }\n >): void {\n // Adapter will override the hooks\n\n const factory = new SocketIoFactory(socket, prefix, hooks!);\n if (enableVoiceEvents) {\n factory.setupVoiceEvents();\n }\n\n if (enableChatEvents) {\n factory.setupChatEvents(socket);\n }\n\n if (enableTranscriptEvents) {\n factory.setupTranscriptEvents(socket);\n }\n }\n\n private setupVoiceEvents(): void {\n const {\n onVoiceInputFile,\n onVoiceInputChunk,\n onVoiceInputCommit,\n onVoiceOutputDelta,\n onVoiceOutputCommit,\n onVoiceOutputFile,\n onVoiceOutputTranscriptDelta,\n onVoiceOutputTranscriptFull,\n } = this.hooks;\n\n const prefix = this.prefixEvent;\n\n if (onVoiceInputFile) {\n this.socket.on(prefix('voice:input_file'), onVoiceInputFile);\n }\n\n if (onVoiceInputChunk) {\n this.socket.on(prefix('voice:input_chunk'), onVoiceInputChunk);\n }\n\n if (onVoiceInputCommit) {\n this.socket.on(prefix('voice:input_commit'), onVoiceInputCommit);\n }\n\n if (onVoiceOutputDelta) {\n this.socket.on(prefix('voice:output_delta'), onVoiceOutputDelta);\n }\n\n if (onVoiceOutputCommit) {\n this.socket.on(prefix('voice:output_commit'), onVoiceOutputCommit);\n }\n\n if (onVoiceOutputFile) {\n this.socket.on(prefix('voice:output_file'), onVoiceOutputFile);\n }\n\n if (onVoiceOutputTranscriptDelta) {\n this.socket.on(\n prefix('voice:output_transcript_delta'),\n onVoiceOutputTranscriptDelta\n );\n }\n\n if (onVoiceOutputTranscriptFull) {\n this.socket.on(\n prefix('voice:output_transcript_full'),\n onVoiceOutputTranscriptFull\n );\n }\n }\n\n private setupChatEvents(_socket: Socket): void {\n // TODO: Implement chat event handler\n }\n\n private setupTranscriptEvents(_socket: Socket): void {\n // TODO: Implement transcript event handlers\n }\n\n private prefixEvent(event: string): string {\n return this.prefix ? `${this.prefix}:${event}` : event;\n }\n}\n"]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Socket } from 'socket.io';
|
|
2
|
+
|
|
3
|
+
type Role = 'system' | 'user' | 'assistant' | string;
|
|
4
|
+
interface BaseMessage {
|
|
5
|
+
/** Unique across the conversation */
|
|
6
|
+
id: string;
|
|
7
|
+
role: Role;
|
|
8
|
+
/** ISO string or Date; normalized when you receive it */
|
|
9
|
+
timestamp: string;
|
|
10
|
+
}
|
|
11
|
+
interface TextMessage extends BaseMessage {
|
|
12
|
+
kind: 'text';
|
|
13
|
+
/** two modes: plain vs. structured */
|
|
14
|
+
content: string | {
|
|
15
|
+
format: 'markdown' | 'html';
|
|
16
|
+
body: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
interface VoiceMessage extends BaseMessage {
|
|
20
|
+
kind: 'voice';
|
|
21
|
+
/** raw bytes or reference */
|
|
22
|
+
data: ArrayBuffer | Blob;
|
|
23
|
+
format: 'mp3' | 'wav' | string;
|
|
24
|
+
durationMs: number;
|
|
25
|
+
/** optional transcript if you run speech-to-text */
|
|
26
|
+
transcript?: string;
|
|
27
|
+
}
|
|
28
|
+
type Message = TextMessage | VoiceMessage;
|
|
29
|
+
|
|
30
|
+
type SocketEventName = 'conversation:create' | 'voice:input_file' | 'voice:input_chunk' | 'voice:input_commit' | 'voice:output_delta' | 'voice:output_commit' | 'voice:output_file' | 'voice:output_transcript_delta' | 'voice:output_transcript_full';
|
|
31
|
+
|
|
32
|
+
type HookContext<T> = {
|
|
33
|
+
socket: T;
|
|
34
|
+
hooks: Hooks<T>;
|
|
35
|
+
};
|
|
36
|
+
type Hooks<SocketType> = {
|
|
37
|
+
onConversationCreated?: (conversationId: string, context: HookContext<SocketType>) => void;
|
|
38
|
+
onVoiceInputFile?: (file: Blob | Uint8Array, context: HookContext<SocketType>) => void;
|
|
39
|
+
onVoiceInputChunk?: (chunk: Uint8Array, context: HookContext<SocketType>) => void;
|
|
40
|
+
onVoiceInputCommit?: (context: HookContext<SocketType>) => void;
|
|
41
|
+
onVoiceOutputDelta?: (chunk: Uint8Array, context: HookContext<SocketType>) => void;
|
|
42
|
+
onVoiceOutputCommit?: (context: HookContext<SocketType>) => void;
|
|
43
|
+
onVoiceOutputFile?: (file: Blob | Uint8Array, context: HookContext<SocketType>) => void;
|
|
44
|
+
onVoiceOutputTranscriptDelta?: (transcriptChunk: string, context: HookContext<SocketType>) => void;
|
|
45
|
+
onVoiceOutputTranscriptFull?: (transcript: string, context: HookContext<SocketType>) => void;
|
|
46
|
+
};
|
|
47
|
+
type BaseSetupSocketHandlersParams<SocketType> = {
|
|
48
|
+
enableVoiceEvents: boolean;
|
|
49
|
+
enableChatEvents: boolean;
|
|
50
|
+
enableTranscriptEvents: boolean;
|
|
51
|
+
prefix?: string;
|
|
52
|
+
hooks?: Hooks<SocketType>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Extra keys supplied by the caller are kept,
|
|
56
|
+
* but if they collide with a base key the base type wins.
|
|
57
|
+
*/
|
|
58
|
+
type SetupSocketHandlersParams<SocketType, Extra = Record<string, never>> = Omit<Extra, keyof BaseSetupSocketHandlersParams<SocketType>> & BaseSetupSocketHandlersParams<SocketType>;
|
|
59
|
+
|
|
60
|
+
declare class SocketIoFactory {
|
|
61
|
+
private socket;
|
|
62
|
+
private prefix;
|
|
63
|
+
private hooks;
|
|
64
|
+
private constructor();
|
|
65
|
+
static setupSocketHandlers({ enableVoiceEvents, enableChatEvents, enableTranscriptEvents, prefix, socket, hooks, }: SetupSocketHandlersParams<Socket, {
|
|
66
|
+
socket: Socket;
|
|
67
|
+
}>): void;
|
|
68
|
+
private setupVoiceEvents;
|
|
69
|
+
private setupChatEvents;
|
|
70
|
+
private setupTranscriptEvents;
|
|
71
|
+
private prefixEvent;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type BaseMessage, type Message, type Role, type SocketEventName, SocketIoFactory, type TextMessage, type VoiceMessage };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Socket } from 'socket.io';
|
|
2
|
+
|
|
3
|
+
type Role = 'system' | 'user' | 'assistant' | string;
|
|
4
|
+
interface BaseMessage {
|
|
5
|
+
/** Unique across the conversation */
|
|
6
|
+
id: string;
|
|
7
|
+
role: Role;
|
|
8
|
+
/** ISO string or Date; normalized when you receive it */
|
|
9
|
+
timestamp: string;
|
|
10
|
+
}
|
|
11
|
+
interface TextMessage extends BaseMessage {
|
|
12
|
+
kind: 'text';
|
|
13
|
+
/** two modes: plain vs. structured */
|
|
14
|
+
content: string | {
|
|
15
|
+
format: 'markdown' | 'html';
|
|
16
|
+
body: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
interface VoiceMessage extends BaseMessage {
|
|
20
|
+
kind: 'voice';
|
|
21
|
+
/** raw bytes or reference */
|
|
22
|
+
data: ArrayBuffer | Blob;
|
|
23
|
+
format: 'mp3' | 'wav' | string;
|
|
24
|
+
durationMs: number;
|
|
25
|
+
/** optional transcript if you run speech-to-text */
|
|
26
|
+
transcript?: string;
|
|
27
|
+
}
|
|
28
|
+
type Message = TextMessage | VoiceMessage;
|
|
29
|
+
|
|
30
|
+
type SocketEventName = 'conversation:create' | 'voice:input_file' | 'voice:input_chunk' | 'voice:input_commit' | 'voice:output_delta' | 'voice:output_commit' | 'voice:output_file' | 'voice:output_transcript_delta' | 'voice:output_transcript_full';
|
|
31
|
+
|
|
32
|
+
type HookContext<T> = {
|
|
33
|
+
socket: T;
|
|
34
|
+
hooks: Hooks<T>;
|
|
35
|
+
};
|
|
36
|
+
type Hooks<SocketType> = {
|
|
37
|
+
onConversationCreated?: (conversationId: string, context: HookContext<SocketType>) => void;
|
|
38
|
+
onVoiceInputFile?: (file: Blob | Uint8Array, context: HookContext<SocketType>) => void;
|
|
39
|
+
onVoiceInputChunk?: (chunk: Uint8Array, context: HookContext<SocketType>) => void;
|
|
40
|
+
onVoiceInputCommit?: (context: HookContext<SocketType>) => void;
|
|
41
|
+
onVoiceOutputDelta?: (chunk: Uint8Array, context: HookContext<SocketType>) => void;
|
|
42
|
+
onVoiceOutputCommit?: (context: HookContext<SocketType>) => void;
|
|
43
|
+
onVoiceOutputFile?: (file: Blob | Uint8Array, context: HookContext<SocketType>) => void;
|
|
44
|
+
onVoiceOutputTranscriptDelta?: (transcriptChunk: string, context: HookContext<SocketType>) => void;
|
|
45
|
+
onVoiceOutputTranscriptFull?: (transcript: string, context: HookContext<SocketType>) => void;
|
|
46
|
+
};
|
|
47
|
+
type BaseSetupSocketHandlersParams<SocketType> = {
|
|
48
|
+
enableVoiceEvents: boolean;
|
|
49
|
+
enableChatEvents: boolean;
|
|
50
|
+
enableTranscriptEvents: boolean;
|
|
51
|
+
prefix?: string;
|
|
52
|
+
hooks?: Hooks<SocketType>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Extra keys supplied by the caller are kept,
|
|
56
|
+
* but if they collide with a base key the base type wins.
|
|
57
|
+
*/
|
|
58
|
+
type SetupSocketHandlersParams<SocketType, Extra = Record<string, never>> = Omit<Extra, keyof BaseSetupSocketHandlersParams<SocketType>> & BaseSetupSocketHandlersParams<SocketType>;
|
|
59
|
+
|
|
60
|
+
declare class SocketIoFactory {
|
|
61
|
+
private socket;
|
|
62
|
+
private prefix;
|
|
63
|
+
private hooks;
|
|
64
|
+
private constructor();
|
|
65
|
+
static setupSocketHandlers({ enableVoiceEvents, enableChatEvents, enableTranscriptEvents, prefix, socket, hooks, }: SetupSocketHandlersParams<Socket, {
|
|
66
|
+
socket: Socket;
|
|
67
|
+
}>): void;
|
|
68
|
+
private setupVoiceEvents;
|
|
69
|
+
private setupChatEvents;
|
|
70
|
+
private setupTranscriptEvents;
|
|
71
|
+
private prefixEvent;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type BaseMessage, type Message, type Role, type SocketEventName, SocketIoFactory, type TextMessage, type VoiceMessage };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// src/api/socket-handler/SocketIoFactory.ts
|
|
2
|
+
var SocketIoFactory = class _SocketIoFactory {
|
|
3
|
+
constructor(socket, prefix, hooks) {
|
|
4
|
+
this.socket = socket;
|
|
5
|
+
this.prefix = prefix;
|
|
6
|
+
this.hooks = hooks;
|
|
7
|
+
}
|
|
8
|
+
static setupSocketHandlers({
|
|
9
|
+
enableVoiceEvents,
|
|
10
|
+
enableChatEvents,
|
|
11
|
+
enableTranscriptEvents,
|
|
12
|
+
prefix = "",
|
|
13
|
+
socket,
|
|
14
|
+
hooks
|
|
15
|
+
}) {
|
|
16
|
+
const factory = new _SocketIoFactory(socket, prefix, hooks);
|
|
17
|
+
if (enableVoiceEvents) {
|
|
18
|
+
factory.setupVoiceEvents();
|
|
19
|
+
}
|
|
20
|
+
if (enableChatEvents) {
|
|
21
|
+
factory.setupChatEvents(socket);
|
|
22
|
+
}
|
|
23
|
+
if (enableTranscriptEvents) {
|
|
24
|
+
factory.setupTranscriptEvents(socket);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
setupVoiceEvents() {
|
|
28
|
+
const {
|
|
29
|
+
onVoiceInputFile,
|
|
30
|
+
onVoiceInputChunk,
|
|
31
|
+
onVoiceInputCommit,
|
|
32
|
+
onVoiceOutputDelta,
|
|
33
|
+
onVoiceOutputCommit,
|
|
34
|
+
onVoiceOutputFile,
|
|
35
|
+
onVoiceOutputTranscriptDelta,
|
|
36
|
+
onVoiceOutputTranscriptFull
|
|
37
|
+
} = this.hooks;
|
|
38
|
+
const prefix = this.prefixEvent;
|
|
39
|
+
if (onVoiceInputFile) {
|
|
40
|
+
this.socket.on(prefix("voice:input_file"), onVoiceInputFile);
|
|
41
|
+
}
|
|
42
|
+
if (onVoiceInputChunk) {
|
|
43
|
+
this.socket.on(prefix("voice:input_chunk"), onVoiceInputChunk);
|
|
44
|
+
}
|
|
45
|
+
if (onVoiceInputCommit) {
|
|
46
|
+
this.socket.on(prefix("voice:input_commit"), onVoiceInputCommit);
|
|
47
|
+
}
|
|
48
|
+
if (onVoiceOutputDelta) {
|
|
49
|
+
this.socket.on(prefix("voice:output_delta"), onVoiceOutputDelta);
|
|
50
|
+
}
|
|
51
|
+
if (onVoiceOutputCommit) {
|
|
52
|
+
this.socket.on(prefix("voice:output_commit"), onVoiceOutputCommit);
|
|
53
|
+
}
|
|
54
|
+
if (onVoiceOutputFile) {
|
|
55
|
+
this.socket.on(prefix("voice:output_file"), onVoiceOutputFile);
|
|
56
|
+
}
|
|
57
|
+
if (onVoiceOutputTranscriptDelta) {
|
|
58
|
+
this.socket.on(
|
|
59
|
+
prefix("voice:output_transcript_delta"),
|
|
60
|
+
onVoiceOutputTranscriptDelta
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
if (onVoiceOutputTranscriptFull) {
|
|
64
|
+
this.socket.on(
|
|
65
|
+
prefix("voice:output_transcript_full"),
|
|
66
|
+
onVoiceOutputTranscriptFull
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
setupChatEvents(_socket) {
|
|
71
|
+
}
|
|
72
|
+
setupTranscriptEvents(_socket) {
|
|
73
|
+
}
|
|
74
|
+
prefixEvent(event) {
|
|
75
|
+
return this.prefix ? `${this.prefix}:${event}` : event;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { SocketIoFactory };
|
|
80
|
+
//# sourceMappingURL=out.js.map
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/api/socket-handler/SocketIoFactory.ts"],"names":[],"mappings":";AAGO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EAKnB,YAAY,QAAgB,QAAgB,OAAsB;AACxE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,OAAO,oBAAoB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF,GAKS;AAGP,UAAM,UAAU,IAAI,iBAAgB,QAAQ,QAAQ,KAAM;AAC1D,QAAI,mBAAmB;AACrB,cAAQ,iBAAiB;AAAA,IAC3B;AAEA,QAAI,kBAAkB;AACpB,cAAQ,gBAAgB,MAAM;AAAA,IAChC;AAEA,QAAI,wBAAwB;AAC1B,cAAQ,sBAAsB,MAAM;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK;AAET,UAAM,SAAS,KAAK;AAEpB,QAAI,kBAAkB;AACpB,WAAK,OAAO,GAAG,OAAO,kBAAkB,GAAG,gBAAgB;AAAA,IAC7D;AAEA,QAAI,mBAAmB;AACrB,WAAK,OAAO,GAAG,OAAO,mBAAmB,GAAG,iBAAiB;AAAA,IAC/D;AAEA,QAAI,oBAAoB;AACtB,WAAK,OAAO,GAAG,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,IACjE;AAEA,QAAI,oBAAoB;AACtB,WAAK,OAAO,GAAG,OAAO,oBAAoB,GAAG,kBAAkB;AAAA,IACjE;AAEA,QAAI,qBAAqB;AACvB,WAAK,OAAO,GAAG,OAAO,qBAAqB,GAAG,mBAAmB;AAAA,IACnE;AAEA,QAAI,mBAAmB;AACrB,WAAK,OAAO,GAAG,OAAO,mBAAmB,GAAG,iBAAiB;AAAA,IAC/D;AAEA,QAAI,8BAA8B;AAChC,WAAK,OAAO;AAAA,QACV,OAAO,+BAA+B;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,6BAA6B;AAC/B,WAAK,OAAO;AAAA,QACV,OAAO,8BAA8B;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAAuB;AAAA,EAE/C;AAAA,EAEQ,sBAAsB,SAAuB;AAAA,EAErD;AAAA,EAEQ,YAAY,OAAuB;AACzC,WAAO,KAAK,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EACnD;AACF","sourcesContent":["import { Socket } from 'socket.io';\nimport { Hooks, SetupSocketHandlersParams } from './socket-factory-types';\n\nexport class SocketIoFactory {\n private socket: Socket;\n private prefix: string;\n private hooks: Hooks<Socket>;\n\n private constructor(socket: Socket, prefix: string, hooks: Hooks<Socket>) {\n this.socket = socket;\n this.prefix = prefix;\n this.hooks = hooks;\n }\n\n static setupSocketHandlers({\n enableVoiceEvents,\n enableChatEvents,\n enableTranscriptEvents,\n prefix = '',\n socket,\n hooks,\n }: SetupSocketHandlersParams<\n Socket,\n {\n socket: Socket;\n }\n >): void {\n // Adapter will override the hooks\n\n const factory = new SocketIoFactory(socket, prefix, hooks!);\n if (enableVoiceEvents) {\n factory.setupVoiceEvents();\n }\n\n if (enableChatEvents) {\n factory.setupChatEvents(socket);\n }\n\n if (enableTranscriptEvents) {\n factory.setupTranscriptEvents(socket);\n }\n }\n\n private setupVoiceEvents(): void {\n const {\n onVoiceInputFile,\n onVoiceInputChunk,\n onVoiceInputCommit,\n onVoiceOutputDelta,\n onVoiceOutputCommit,\n onVoiceOutputFile,\n onVoiceOutputTranscriptDelta,\n onVoiceOutputTranscriptFull,\n } = this.hooks;\n\n const prefix = this.prefixEvent;\n\n if (onVoiceInputFile) {\n this.socket.on(prefix('voice:input_file'), onVoiceInputFile);\n }\n\n if (onVoiceInputChunk) {\n this.socket.on(prefix('voice:input_chunk'), onVoiceInputChunk);\n }\n\n if (onVoiceInputCommit) {\n this.socket.on(prefix('voice:input_commit'), onVoiceInputCommit);\n }\n\n if (onVoiceOutputDelta) {\n this.socket.on(prefix('voice:output_delta'), onVoiceOutputDelta);\n }\n\n if (onVoiceOutputCommit) {\n this.socket.on(prefix('voice:output_commit'), onVoiceOutputCommit);\n }\n\n if (onVoiceOutputFile) {\n this.socket.on(prefix('voice:output_file'), onVoiceOutputFile);\n }\n\n if (onVoiceOutputTranscriptDelta) {\n this.socket.on(\n prefix('voice:output_transcript_delta'),\n onVoiceOutputTranscriptDelta\n );\n }\n\n if (onVoiceOutputTranscriptFull) {\n this.socket.on(\n prefix('voice:output_transcript_full'),\n onVoiceOutputTranscriptFull\n );\n }\n }\n\n private setupChatEvents(_socket: Socket): void {\n // TODO: Implement chat event handler\n }\n\n private setupTranscriptEvents(_socket: Socket): void {\n // TODO: Implement transcript event handlers\n }\n\n private prefixEvent(event: string): string {\n return this.prefix ? `${this.prefix}:${event}` : event;\n }\n}\n"]}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var messages = require('@langchain/core/messages');
|
|
4
|
+
var effect = require('effect');
|
|
5
|
+
|
|
6
|
+
// src/helper/transform-messages/TransformMessages.ts
|
|
7
|
+
var humanAndAI = (message) => message instanceof messages.HumanMessage || message instanceof messages.AIMessage;
|
|
8
|
+
var humanOnly = (message) => message instanceof messages.HumanMessage;
|
|
9
|
+
var aiOnly = (message) => message instanceof messages.AIMessage;
|
|
10
|
+
var includingTags = (message, tags) => {
|
|
11
|
+
if (tags) {
|
|
12
|
+
return tags.some(
|
|
13
|
+
(tag) => Array.isArray(message.additional_kwargs?.tags) ? message.additional_kwargs?.tags.includes(tag) : false
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
};
|
|
18
|
+
var excludingTags = (message, tags) => {
|
|
19
|
+
if (tags) {
|
|
20
|
+
return !tags.some(
|
|
21
|
+
(tag) => Array.isArray(message.additional_kwargs?.tags) ? message.additional_kwargs?.tags.includes(tag) : false
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
};
|
|
26
|
+
var typeOnFilter = {
|
|
27
|
+
["HumanAndAI" /* HumanAndAI */]: humanAndAI,
|
|
28
|
+
["HumanOnly" /* HumanOnly */]: humanOnly,
|
|
29
|
+
["AIOnly" /* AIOnly */]: aiOnly,
|
|
30
|
+
["IncludingTags" /* IncludingTags */]: includingTags,
|
|
31
|
+
["ExcludingTags" /* ExcludingTags */]: excludingTags
|
|
32
|
+
};
|
|
33
|
+
function concise(messages$1) {
|
|
34
|
+
return messages$1.map((message) => {
|
|
35
|
+
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
36
|
+
return `${prefix}: ${message.content}`;
|
|
37
|
+
}).join("\n");
|
|
38
|
+
}
|
|
39
|
+
function verbose(messages$1) {
|
|
40
|
+
return messages$1.map((message) => {
|
|
41
|
+
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
42
|
+
return `${prefix}:
|
|
43
|
+
${message.content}`;
|
|
44
|
+
}).join("\n-------------------\n");
|
|
45
|
+
}
|
|
46
|
+
function redactAi(messages$1) {
|
|
47
|
+
return messages$1.map((message) => {
|
|
48
|
+
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
49
|
+
const content = message instanceof messages.AIMessage ? "[...]" : message.content;
|
|
50
|
+
return `${prefix}: ${content}`;
|
|
51
|
+
}).join("\n");
|
|
52
|
+
}
|
|
53
|
+
function redactHuman(messages$1) {
|
|
54
|
+
return messages$1.map((message) => {
|
|
55
|
+
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
56
|
+
const content = message instanceof messages.AIMessage ? "[...]" : message.content;
|
|
57
|
+
return `${prefix}: ${content}`;
|
|
58
|
+
}).join("\n");
|
|
59
|
+
}
|
|
60
|
+
var typeOnFormatter = {
|
|
61
|
+
["concise" /* Concise */]: concise,
|
|
62
|
+
["verbose" /* Verbose */]: verbose,
|
|
63
|
+
["redact-ai" /* RedactAi */]: redactAi,
|
|
64
|
+
["redact-human" /* RedactHuman */]: redactHuman
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/helper/transform-messages/TransformMessages.ts
|
|
68
|
+
var TransformMessages = class _TransformMessages {
|
|
69
|
+
constructor(effect) {
|
|
70
|
+
this.effect = effect;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a new TransformMessages from an array of messages.
|
|
74
|
+
*/
|
|
75
|
+
static from(messages) {
|
|
76
|
+
return new _TransformMessages(effect.Effect.succeed(messages));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Filter messages based on a predicate function
|
|
80
|
+
*/
|
|
81
|
+
filter(predicate, tags) {
|
|
82
|
+
let finalPredicate;
|
|
83
|
+
if (typeof predicate === "string") {
|
|
84
|
+
finalPredicate = typeOnFilter[predicate];
|
|
85
|
+
} else {
|
|
86
|
+
finalPredicate = predicate;
|
|
87
|
+
}
|
|
88
|
+
return new _TransformMessages(
|
|
89
|
+
effect.pipe(
|
|
90
|
+
this.effect,
|
|
91
|
+
effect.Effect.map(
|
|
92
|
+
(messages) => messages.filter((message) => finalPredicate(message, tags))
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Take only the last n messages, but safely.
|
|
99
|
+
* Tool calls should not be separated from the last human message.
|
|
100
|
+
* Ensures all tool call conversations in the last n messages are complete.
|
|
101
|
+
*/
|
|
102
|
+
safelyTakeLast(n, pruneAfterNOvershootingMessages = 0) {
|
|
103
|
+
return new _TransformMessages(
|
|
104
|
+
effect.pipe(
|
|
105
|
+
this.effect,
|
|
106
|
+
effect.Effect.map((messages$1) => {
|
|
107
|
+
const total = messages$1.length;
|
|
108
|
+
if (n <= 0 || total === 0)
|
|
109
|
+
return [];
|
|
110
|
+
const start = Math.max(0, total - n);
|
|
111
|
+
const end = total;
|
|
112
|
+
const lastSlice = messages$1.slice(start, end);
|
|
113
|
+
if (lastSlice[0] instanceof messages.ToolMessage && lastSlice[0].tool_call_id) {
|
|
114
|
+
let messagesToInclude = [];
|
|
115
|
+
const remainingMessages = messages$1.slice(0, start);
|
|
116
|
+
for (let i = remainingMessages.length - 1; i >= 0; i--) {
|
|
117
|
+
const msg = remainingMessages[i];
|
|
118
|
+
if (pruneAfterNOvershootingMessages > 0 && messagesToInclude.length - 1 >= pruneAfterNOvershootingMessages) {
|
|
119
|
+
messagesToInclude = [];
|
|
120
|
+
const filteredSlice = [];
|
|
121
|
+
let foundFirstNonToolMessage = false;
|
|
122
|
+
for (let i2 = 0; i2 < lastSlice.length; i2++) {
|
|
123
|
+
const msg2 = lastSlice[i2];
|
|
124
|
+
if (msg2 instanceof messages.ToolMessage) {
|
|
125
|
+
if (foundFirstNonToolMessage) {
|
|
126
|
+
filteredSlice.push(msg2);
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
foundFirstNonToolMessage = true;
|
|
130
|
+
filteredSlice.push(msg2);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return filteredSlice;
|
|
134
|
+
}
|
|
135
|
+
if (msg instanceof messages.AIMessage && Array.isArray(msg.tool_calls)) {
|
|
136
|
+
messagesToInclude.push(msg);
|
|
137
|
+
break;
|
|
138
|
+
} else if (msg instanceof messages.ToolMessage) {
|
|
139
|
+
messagesToInclude.push(msg);
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error(
|
|
142
|
+
"Messages array invalid no adjacent AI message found"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return [...messagesToInclude.reverse(), ...lastSlice];
|
|
147
|
+
} else {
|
|
148
|
+
return lastSlice;
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Take only the last n messages
|
|
156
|
+
*/
|
|
157
|
+
last(n) {
|
|
158
|
+
return new _TransformMessages(
|
|
159
|
+
effect.pipe(
|
|
160
|
+
this.effect,
|
|
161
|
+
effect.Effect.map((messages) => messages.slice(-n))
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Take only the first n messages
|
|
167
|
+
*/
|
|
168
|
+
first(n) {
|
|
169
|
+
return new _TransformMessages(
|
|
170
|
+
effect.pipe(
|
|
171
|
+
this.effect,
|
|
172
|
+
effect.Effect.map((messages) => messages.slice(0, n))
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Skip the first n messages
|
|
178
|
+
*/
|
|
179
|
+
skip(n) {
|
|
180
|
+
return new _TransformMessages(
|
|
181
|
+
effect.pipe(
|
|
182
|
+
this.effect,
|
|
183
|
+
effect.Effect.map((messages) => messages.slice(n))
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Reverse the order of messages
|
|
189
|
+
*/
|
|
190
|
+
reverse() {
|
|
191
|
+
return new _TransformMessages(
|
|
192
|
+
effect.pipe(
|
|
193
|
+
this.effect,
|
|
194
|
+
effect.Effect.map((messages) => [...messages].reverse())
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Map over messages with a transformation function
|
|
200
|
+
*/
|
|
201
|
+
map(fn) {
|
|
202
|
+
return new _TransformMessages(
|
|
203
|
+
effect.pipe(
|
|
204
|
+
this.effect,
|
|
205
|
+
effect.Effect.map((messages) => messages.map(fn))
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Format messages according to the specified format type
|
|
211
|
+
*/
|
|
212
|
+
format(formatType) {
|
|
213
|
+
return effect.pipe(
|
|
214
|
+
this.effect,
|
|
215
|
+
effect.Effect.map((messages) => {
|
|
216
|
+
if (formatType === "json" /* JSON */) {
|
|
217
|
+
return JSON.stringify(messages, null, 2);
|
|
218
|
+
}
|
|
219
|
+
const formatter = typeOnFormatter[formatType];
|
|
220
|
+
return formatter(messages);
|
|
221
|
+
})
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
// Sink methods
|
|
225
|
+
/**
|
|
226
|
+
* Convert to array - runs the effect and returns the result
|
|
227
|
+
*/
|
|
228
|
+
toArray() {
|
|
229
|
+
return this.effect;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Convert to string - runs the effect and returns JSON string
|
|
233
|
+
*/
|
|
234
|
+
toString() {
|
|
235
|
+
return effect.pipe(
|
|
236
|
+
this.effect,
|
|
237
|
+
effect.Effect.map((messages) => JSON.stringify(messages, null, 2))
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get the count of messages
|
|
242
|
+
*/
|
|
243
|
+
count() {
|
|
244
|
+
return effect.pipe(
|
|
245
|
+
this.effect,
|
|
246
|
+
effect.Effect.map((messages) => messages.length)
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
exports.TransformMessages = TransformMessages;
|
|
252
|
+
//# sourceMappingURL=out.js.map
|
|
253
|
+
//# sourceMappingURL=index.cjs.map
|