@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 ADDED
@@ -0,0 +1,72 @@
1
+
2
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/Pascal-Lohscheidt/build-ai/tree/main.svg?style=svg)](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