@agentuity/runtime 0.0.103 → 0.0.105

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.
Files changed (67) hide show
  1. package/README.md +61 -35
  2. package/dist/_config.d.ts.map +1 -1
  3. package/dist/_config.js +9 -2
  4. package/dist/_config.js.map +1 -1
  5. package/dist/agent.d.ts.map +1 -1
  6. package/dist/agent.js +6 -0
  7. package/dist/agent.js.map +1 -1
  8. package/dist/app.d.ts +5 -2
  9. package/dist/app.d.ts.map +1 -1
  10. package/dist/app.js.map +1 -1
  11. package/dist/eval.d.ts +2 -0
  12. package/dist/eval.d.ts.map +1 -1
  13. package/dist/handlers/cron.d.ts +47 -0
  14. package/dist/handlers/cron.d.ts.map +1 -0
  15. package/dist/handlers/cron.js +49 -0
  16. package/dist/handlers/cron.js.map +1 -0
  17. package/dist/handlers/index.d.ts +5 -0
  18. package/dist/handlers/index.d.ts.map +1 -0
  19. package/dist/handlers/index.js +5 -0
  20. package/dist/handlers/index.js.map +1 -0
  21. package/dist/handlers/sse.d.ts +74 -0
  22. package/dist/handlers/sse.d.ts.map +1 -0
  23. package/dist/handlers/sse.js +70 -0
  24. package/dist/handlers/sse.js.map +1 -0
  25. package/dist/handlers/stream.d.ts +52 -0
  26. package/dist/handlers/stream.d.ts.map +1 -0
  27. package/dist/handlers/stream.js +75 -0
  28. package/dist/handlers/stream.js.map +1 -0
  29. package/dist/handlers/websocket.d.ts +49 -0
  30. package/dist/handlers/websocket.d.ts.map +1 -0
  31. package/dist/handlers/websocket.js +130 -0
  32. package/dist/handlers/websocket.js.map +1 -0
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +4 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/otel/logger.d.ts +1 -4
  38. package/dist/otel/logger.d.ts.map +1 -1
  39. package/dist/otel/logger.js +11 -2
  40. package/dist/otel/logger.js.map +1 -1
  41. package/dist/router.d.ts +46 -236
  42. package/dist/router.d.ts.map +1 -1
  43. package/dist/router.js +82 -349
  44. package/dist/router.js.map +1 -1
  45. package/dist/workbench.d.ts +6 -2
  46. package/dist/workbench.d.ts.map +1 -1
  47. package/dist/workbench.js +29 -26
  48. package/dist/workbench.js.map +1 -1
  49. package/package.json +5 -7
  50. package/src/_config.ts +9 -2
  51. package/src/agent.ts +6 -0
  52. package/src/app.ts +7 -2
  53. package/src/eval.ts +2 -0
  54. package/src/handlers/cron.ts +70 -0
  55. package/src/handlers/index.ts +4 -0
  56. package/src/handlers/sse.ts +118 -0
  57. package/src/handlers/stream.ts +86 -0
  58. package/src/handlers/websocket.ts +153 -0
  59. package/src/index.ts +16 -3
  60. package/src/otel/logger.ts +13 -2
  61. package/src/router.ts +110 -597
  62. package/src/workbench.ts +30 -27
  63. package/dist/io/email.d.ts +0 -77
  64. package/dist/io/email.d.ts.map +0 -1
  65. package/dist/io/email.js +0 -162
  66. package/dist/io/email.js.map +0 -1
  67. package/src/io/email.ts +0 -191
package/src/workbench.ts CHANGED
@@ -3,7 +3,7 @@ import { timingSafeEqual } from 'node:crypto';
3
3
  import { toJSONSchema } from '@agentuity/server';
4
4
  import { getAgents, createAgentMiddleware } from './agent';
5
5
  import { createRouter } from './router';
6
- import type { WebSocketConnection } from './router';
6
+ import { websocket, type WebSocketConnection } from './handlers/websocket';
7
7
  import { privateContext } from './_server';
8
8
  import { getThreadProvider } from './_services';
9
9
  import { loadBuildMetadata, getAgentMetadataByAgentId, hasMetadata } from './_metadata';
@@ -255,7 +255,7 @@ export const createWorkbenchRouter = () => {
255
255
  router.use('/_agentuity/workbench/*', createAgentMiddleware(''));
256
256
 
257
257
  // Add workbench routes
258
- router.websocket('/_agentuity/workbench/ws', createWorkbenchWebsocketRoute());
258
+ router.get('/_agentuity/workbench/ws', websocket(createWorkbenchWebsocketHandler()));
259
259
  router.get('/_agentuity/workbench/metadata.json', createWorkbenchMetadataRoute());
260
260
  router.get('/_agentuity/workbench/sample', createWorkbenchSampleRoute());
261
261
  router.get('/_agentuity/workbench/state', createWorkbenchStateRoute());
@@ -506,35 +506,38 @@ export const createWorkbenchMetadataRoute = (): Handler => {
506
506
  // Store WebSocket connections to notify them on app restart
507
507
  const workbenchWebSockets = new Set<WebSocketConnection>();
508
508
 
509
- export const createWorkbenchWebsocketRoute = () => {
510
- return (_ctx: Context) => {
511
- return (ws: WebSocketConnection) => {
512
- ws.onOpen(() => {
513
- workbenchWebSockets.add(ws);
514
- ws.send('alive');
515
- });
509
+ export const createWorkbenchWebsocketHandler = () => {
510
+ return (_c: Context, ws: WebSocketConnection) => {
511
+ ws.onOpen(() => {
512
+ workbenchWebSockets.add(ws);
513
+ ws.send('alive');
514
+ });
516
515
 
517
- ws.onMessage((event) => {
518
- const message = event.data;
519
-
520
- // If a client sends a message (CLI), broadcast to all other clients
521
- if (message === 'restarting' || message === 'alive') {
522
- // Broadcast the message to all other clients (excluding this CLI connection)
523
- for (const clientWs of workbenchWebSockets) {
524
- if (clientWs !== ws) {
525
- try {
526
- clientWs.send(message);
527
- } catch (_error) {
528
- workbenchWebSockets.delete(clientWs);
529
- }
516
+ ws.onMessage((event) => {
517
+ const message = (event as MessageEvent).data;
518
+
519
+ // If a client sends a message (CLI), broadcast to all other clients
520
+ if (message === 'restarting' || message === 'alive') {
521
+ // Broadcast the message to all other clients (excluding this CLI connection)
522
+ for (const clientWs of workbenchWebSockets) {
523
+ if (clientWs !== ws) {
524
+ try {
525
+ clientWs.send(message);
526
+ } catch (_error) {
527
+ workbenchWebSockets.delete(clientWs);
530
528
  }
531
529
  }
532
530
  }
533
- });
531
+ }
532
+ });
534
533
 
535
- ws.onClose(() => {
536
- workbenchWebSockets.delete(ws);
537
- });
538
- };
534
+ ws.onClose(() => {
535
+ workbenchWebSockets.delete(ws);
536
+ });
539
537
  };
540
538
  };
539
+
540
+ /**
541
+ * @deprecated Use createWorkbenchWebsocketHandler instead
542
+ */
543
+ export const createWorkbenchWebsocketRoute = createWorkbenchWebsocketHandler;
@@ -1,77 +0,0 @@
1
- import { type ParsedMail, type Headers } from 'mailparser';
2
- /**
3
- * A class representing an email with common information for processing.
4
- *
5
- * This class wraps the parsed email message and provides convenient accessor methods
6
- * for common email properties like subject, sender, recipient, body content, etc.
7
- */
8
- export declare class Email {
9
- private readonly _message;
10
- constructor(data: ParsedMail);
11
- toString(): string;
12
- /**
13
- * The date of the email.
14
- */
15
- date(): Date | null;
16
- /**
17
- * The message ID of the email.
18
- */
19
- messageId(): string | null;
20
- /**
21
- * The headers of the email.
22
- */
23
- headers(): Headers;
24
- /**
25
- * The email address of the recipient or null if there is no recipient.
26
- *
27
- * If the email has multiple recipients, the email addresses are comma separated.
28
- */
29
- to(): string | null;
30
- /**
31
- * The email address of the sender or null if there is no sender.
32
- */
33
- fromEmail(): string | null;
34
- /**
35
- * The name of the sender or null if there is no name.
36
- */
37
- fromName(): string | null;
38
- /**
39
- * The email address of the first recipient or null if there is no recipient.
40
- */
41
- toEmail(): string | null;
42
- /**
43
- * The name of the first recipient or null if there is no name.
44
- */
45
- toName(): string | null;
46
- /**
47
- * The subject of the email or null if there is no subject.
48
- */
49
- subject(): string | null;
50
- /**
51
- * The plain text body of the email or null if there is no plain text body.
52
- */
53
- text(): string | null;
54
- /**
55
- * The HTML body of the email or null if there is no HTML body.
56
- */
57
- html(): string | null;
58
- /**
59
- * The attachments of the email or an empty array if there are no attachments.
60
- *
61
- * Note: Attachment handling is minimal in this implementation.
62
- * For full attachment support with SSRF protection, see the sdk-js implementation.
63
- */
64
- attachments(): Array<{
65
- filename: string;
66
- contentType: string;
67
- }>;
68
- }
69
- /**
70
- * Parse an email from a buffer and return an Email object.
71
- *
72
- * @param data - The raw RFC822 email message as a Buffer
73
- * @returns A promise that resolves to an Email object
74
- * @throws Error if the email cannot be parsed or if the input is not a valid RFC822 message
75
- */
76
- export declare function parseEmail(data: Buffer): Promise<Email>;
77
- //# sourceMappingURL=email.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/io/email.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,EAAoC,MAAM,YAAY,CAAC;AAE7F;;;;;GAKG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;gBAE1B,IAAI,EAAE,UAAU;IAI5B,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,IAAI,IAAI,IAAI,GAAG,IAAI;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;;;OAIG;IACH,EAAE,IAAI,MAAM,GAAG,IAAI;IAgBnB;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,IAAI;IAIzB;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,IAAI;IAaxB;;OAEG;IACH,MAAM,IAAI,MAAM,GAAG,IAAI;IAavB;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB;;OAEG;IACH,IAAI,IAAI,MAAM,GAAG,IAAI;IAIrB;;OAEG;IACH,IAAI,IAAI,MAAM,GAAG,IAAI;IAIrB;;;;;OAKG;IACH,WAAW,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAS/D;AAiBD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAsB7D"}
package/dist/io/email.js DELETED
@@ -1,162 +0,0 @@
1
- import { StructuredError } from '@agentuity/core';
2
- import { simpleParser } from 'mailparser';
3
- /**
4
- * A class representing an email with common information for processing.
5
- *
6
- * This class wraps the parsed email message and provides convenient accessor methods
7
- * for common email properties like subject, sender, recipient, body content, etc.
8
- */
9
- export class Email {
10
- _message;
11
- constructor(data) {
12
- this._message = data;
13
- }
14
- toString() {
15
- return `[Email id=${this.messageId()},from=${this.fromEmail()},subject=${this.subject()}]`;
16
- }
17
- /**
18
- * The date of the email.
19
- */
20
- date() {
21
- return this._message.date ?? null;
22
- }
23
- /**
24
- * The message ID of the email.
25
- */
26
- messageId() {
27
- return this._message.messageId ?? null;
28
- }
29
- /**
30
- * The headers of the email.
31
- */
32
- headers() {
33
- return this._message.headers;
34
- }
35
- /**
36
- * The email address of the recipient or null if there is no recipient.
37
- *
38
- * If the email has multiple recipients, the email addresses are comma separated.
39
- */
40
- to() {
41
- if (!this._message.to) {
42
- return null;
43
- }
44
- if (Array.isArray(this._message.to)) {
45
- return this._message.to
46
- .map((addr) => (addr.text ?? '').trim())
47
- .filter((text) => text.length > 0)
48
- .join(', ');
49
- }
50
- if (typeof this._message.to === 'object' && 'text' in this._message.to) {
51
- return this._message.to.text ? this._message.to.text.trim() : null;
52
- }
53
- return null;
54
- }
55
- /**
56
- * The email address of the sender or null if there is no sender.
57
- */
58
- fromEmail() {
59
- return this._message.from?.value[0]?.address ?? null;
60
- }
61
- /**
62
- * The name of the sender or null if there is no name.
63
- */
64
- fromName() {
65
- return this._message.from?.value[0]?.name ?? null;
66
- }
67
- /**
68
- * The email address of the first recipient or null if there is no recipient.
69
- */
70
- toEmail() {
71
- if (!this._message.to) {
72
- return null;
73
- }
74
- if (Array.isArray(this._message.to)) {
75
- return this._message.to[0]?.value[0]?.address ?? null;
76
- }
77
- if (typeof this._message.to === 'object' && 'value' in this._message.to) {
78
- return this._message.to.value[0]?.address ?? null;
79
- }
80
- return null;
81
- }
82
- /**
83
- * The name of the first recipient or null if there is no name.
84
- */
85
- toName() {
86
- if (!this._message.to) {
87
- return null;
88
- }
89
- if (Array.isArray(this._message.to)) {
90
- return this._message.to[0]?.value[0]?.name ?? null;
91
- }
92
- if (typeof this._message.to === 'object' && 'value' in this._message.to) {
93
- return this._message.to.value[0]?.name ?? null;
94
- }
95
- return null;
96
- }
97
- /**
98
- * The subject of the email or null if there is no subject.
99
- */
100
- subject() {
101
- return this._message.subject ?? null;
102
- }
103
- /**
104
- * The plain text body of the email or null if there is no plain text body.
105
- */
106
- text() {
107
- return this._message.text ?? null;
108
- }
109
- /**
110
- * The HTML body of the email or null if there is no HTML body.
111
- */
112
- html() {
113
- return this._message.html ? this._message.html : null;
114
- }
115
- /**
116
- * The attachments of the email or an empty array if there are no attachments.
117
- *
118
- * Note: Attachment handling is minimal in this implementation.
119
- * For full attachment support with SSRF protection, see the sdk-js implementation.
120
- */
121
- attachments() {
122
- if (!this._message.attachments || this._message.attachments.length === 0) {
123
- return [];
124
- }
125
- return this._message.attachments.map((att) => ({
126
- filename: att.filename ?? 'unknown',
127
- contentType: att.contentType ?? 'application/octet-stream',
128
- }));
129
- }
130
- }
131
- const InvalidEmailEmptyError = StructuredError('InvalidEmailEmptyError', 'Failed to parse email: empty buffer');
132
- const InvalidEmailHeadersError = StructuredError('InvalidEmailHeadersError', 'Failed to parse email: missing headers');
133
- const InvalidEmailParseError = StructuredError('InvalidEmailParseError', 'Failed to parse email: body was invalid')();
134
- /**
135
- * Parse an email from a buffer and return an Email object.
136
- *
137
- * @param data - The raw RFC822 email message as a Buffer
138
- * @returns A promise that resolves to an Email object
139
- * @throws Error if the email cannot be parsed or if the input is not a valid RFC822 message
140
- */
141
- export async function parseEmail(data) {
142
- if (data.length === 0) {
143
- throw new InvalidEmailEmptyError();
144
- }
145
- const first16KB = data.slice(0, 16384).toString('utf-8', 0, Math.min(data.length, 16384));
146
- const hasHeaders = /(^|\r?\n)[!-9;-~]+:\s/.test(first16KB);
147
- if (!hasHeaders) {
148
- throw new InvalidEmailHeadersError();
149
- }
150
- try {
151
- const message = await simpleParser(data);
152
- return new Email(message);
153
- }
154
- catch (error) {
155
- throw new InvalidEmailParseError({
156
- bufferSize: data.length,
157
- preview: data.subarray(0, 50).toString('hex'),
158
- cause: error,
159
- });
160
- }
161
- }
162
- //# sourceMappingURL=email.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"email.js","sourceRoot":"","sources":["../../src/io/email.ts"],"names":[],"mappings":"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"}
package/src/io/email.ts DELETED
@@ -1,191 +0,0 @@
1
- import { StructuredError } from '@agentuity/core';
2
- import { type ParsedMail, type Headers, simpleParser, type AddressObject } from 'mailparser';
3
-
4
- /**
5
- * A class representing an email with common information for processing.
6
- *
7
- * This class wraps the parsed email message and provides convenient accessor methods
8
- * for common email properties like subject, sender, recipient, body content, etc.
9
- */
10
- export class Email {
11
- private readonly _message: ParsedMail;
12
-
13
- constructor(data: ParsedMail) {
14
- this._message = data;
15
- }
16
-
17
- toString(): string {
18
- return `[Email id=${this.messageId()},from=${this.fromEmail()},subject=${this.subject()}]`;
19
- }
20
-
21
- /**
22
- * The date of the email.
23
- */
24
- date(): Date | null {
25
- return this._message.date ?? null;
26
- }
27
-
28
- /**
29
- * The message ID of the email.
30
- */
31
- messageId(): string | null {
32
- return this._message.messageId ?? null;
33
- }
34
-
35
- /**
36
- * The headers of the email.
37
- */
38
- headers(): Headers {
39
- return this._message.headers;
40
- }
41
-
42
- /**
43
- * The email address of the recipient or null if there is no recipient.
44
- *
45
- * If the email has multiple recipients, the email addresses are comma separated.
46
- */
47
- to(): string | null {
48
- if (!this._message.to) {
49
- return null;
50
- }
51
- if (Array.isArray(this._message.to)) {
52
- return this._message.to
53
- .map((addr: AddressObject) => (addr.text ?? '').trim())
54
- .filter((text: string) => text.length > 0)
55
- .join(', ');
56
- }
57
- if (typeof this._message.to === 'object' && 'text' in this._message.to) {
58
- return this._message.to.text ? this._message.to.text.trim() : null;
59
- }
60
- return null;
61
- }
62
-
63
- /**
64
- * The email address of the sender or null if there is no sender.
65
- */
66
- fromEmail(): string | null {
67
- return this._message.from?.value[0]?.address ?? null;
68
- }
69
-
70
- /**
71
- * The name of the sender or null if there is no name.
72
- */
73
- fromName(): string | null {
74
- return this._message.from?.value[0]?.name ?? null;
75
- }
76
-
77
- /**
78
- * The email address of the first recipient or null if there is no recipient.
79
- */
80
- toEmail(): string | null {
81
- if (!this._message.to) {
82
- return null;
83
- }
84
- if (Array.isArray(this._message.to)) {
85
- return this._message.to[0]?.value[0]?.address ?? null;
86
- }
87
- if (typeof this._message.to === 'object' && 'value' in this._message.to) {
88
- return this._message.to.value[0]?.address ?? null;
89
- }
90
- return null;
91
- }
92
-
93
- /**
94
- * The name of the first recipient or null if there is no name.
95
- */
96
- toName(): string | null {
97
- if (!this._message.to) {
98
- return null;
99
- }
100
- if (Array.isArray(this._message.to)) {
101
- return this._message.to[0]?.value[0]?.name ?? null;
102
- }
103
- if (typeof this._message.to === 'object' && 'value' in this._message.to) {
104
- return this._message.to.value[0]?.name ?? null;
105
- }
106
- return null;
107
- }
108
-
109
- /**
110
- * The subject of the email or null if there is no subject.
111
- */
112
- subject(): string | null {
113
- return this._message.subject ?? null;
114
- }
115
-
116
- /**
117
- * The plain text body of the email or null if there is no plain text body.
118
- */
119
- text(): string | null {
120
- return this._message.text ?? null;
121
- }
122
-
123
- /**
124
- * The HTML body of the email or null if there is no HTML body.
125
- */
126
- html(): string | null {
127
- return this._message.html ? this._message.html : null;
128
- }
129
-
130
- /**
131
- * The attachments of the email or an empty array if there are no attachments.
132
- *
133
- * Note: Attachment handling is minimal in this implementation.
134
- * For full attachment support with SSRF protection, see the sdk-js implementation.
135
- */
136
- attachments(): Array<{ filename: string; contentType: string }> {
137
- if (!this._message.attachments || this._message.attachments.length === 0) {
138
- return [];
139
- }
140
- return this._message.attachments.map((att: { filename?: string; contentType?: string }) => ({
141
- filename: att.filename ?? 'unknown',
142
- contentType: att.contentType ?? 'application/octet-stream',
143
- }));
144
- }
145
- }
146
-
147
- const InvalidEmailEmptyError = StructuredError(
148
- 'InvalidEmailEmptyError',
149
- 'Failed to parse email: empty buffer'
150
- );
151
-
152
- const InvalidEmailHeadersError = StructuredError(
153
- 'InvalidEmailHeadersError',
154
- 'Failed to parse email: missing headers'
155
- );
156
-
157
- const InvalidEmailParseError = StructuredError(
158
- 'InvalidEmailParseError',
159
- 'Failed to parse email: body was invalid'
160
- )<{ bufferSize: number; preview?: string }>();
161
-
162
- /**
163
- * Parse an email from a buffer and return an Email object.
164
- *
165
- * @param data - The raw RFC822 email message as a Buffer
166
- * @returns A promise that resolves to an Email object
167
- * @throws Error if the email cannot be parsed or if the input is not a valid RFC822 message
168
- */
169
- export async function parseEmail(data: Buffer): Promise<Email> {
170
- if (data.length === 0) {
171
- throw new InvalidEmailEmptyError();
172
- }
173
-
174
- const first16KB = data.slice(0, 16384).toString('utf-8', 0, Math.min(data.length, 16384));
175
- const hasHeaders = /(^|\r?\n)[!-9;-~]+:\s/.test(first16KB);
176
-
177
- if (!hasHeaders) {
178
- throw new InvalidEmailHeadersError();
179
- }
180
-
181
- try {
182
- const message = await simpleParser(data);
183
- return new Email(message);
184
- } catch (error) {
185
- throw new InvalidEmailParseError({
186
- bufferSize: data.length,
187
- preview: data.subarray(0, 50).toString('hex'),
188
- cause: error,
189
- });
190
- }
191
- }