@reminix/runtime 0.4.0 → 0.6.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.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Hono server for hosting AI agents.
3
+ */
4
+ import { Hono } from 'hono';
5
+ import { Agent } from './agent';
6
+ /**
7
+ * Options for the serve function.
8
+ */
9
+ export interface ServeOptions {
10
+ /** Host to bind to (default: '0.0.0.0') */
11
+ host?: string;
12
+ /** Port to listen on (default: 8080) */
13
+ port?: number;
14
+ }
15
+ /**
16
+ * Create a Hono app with agent routes.
17
+ *
18
+ * @param agents - List of agents to serve
19
+ * @returns Configured Hono app
20
+ */
21
+ export declare function createApp(agents: Agent[]): Hono;
22
+ /**
23
+ * Start a server hosting the provided agents.
24
+ *
25
+ * @param agents - A single agent or array of agents to serve
26
+ * @param options - Server options (host, port)
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const agent = new Agent('my-agent');
31
+ * agent.onInvoke(async (input) => ({ output: 'hello' }));
32
+ *
33
+ * serve(agent, { port: 8080 });
34
+ * // or
35
+ * serve([agent1, agent2], { port: 8080 });
36
+ * ```
37
+ */
38
+ export declare function serve(agents: Agent | Agent[], options?: ServeOptions): void;
39
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAE,KAAK,EAAmC,MAAM,SAAS,CAAC;AAcjE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAiL/C;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,IAAI,CA8B/E"}
package/dist/server.js ADDED
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Hono server for hosting AI agents.
3
+ */
4
+ import { Hono } from 'hono';
5
+ import { streamSSE } from 'hono/streaming';
6
+ import { serve as honoServe } from '@hono/node-server';
7
+ import { AgentError, NotImplementedError } from './agent';
8
+ import { streamToSse } from './streaming';
9
+ import { ChatRequestSchema, InvokeRequestSchema, } from './types';
10
+ import { VERSION } from './version';
11
+ /**
12
+ * Create a Hono app with agent routes.
13
+ *
14
+ * @param agents - List of agents to serve
15
+ * @returns Configured Hono app
16
+ */
17
+ export function createApp(agents) {
18
+ const app = new Hono();
19
+ // Build agent registry
20
+ const registry = new Map();
21
+ for (const agent of agents) {
22
+ if (registry.has(agent.name)) {
23
+ throw new Error(`Duplicate agent name: ${agent.name}`);
24
+ }
25
+ registry.set(agent.name, agent);
26
+ }
27
+ // Health check endpoint
28
+ app.get('/health', (c) => {
29
+ const response = {
30
+ status: 'healthy',
31
+ agents: Array.from(registry.keys()),
32
+ };
33
+ return c.json(response);
34
+ });
35
+ // Discovery endpoint for Reminix platform
36
+ app.get('/_discover', (c) => {
37
+ const response = {
38
+ runtime: {
39
+ version: VERSION,
40
+ language: 'typescript',
41
+ framework: 'hono',
42
+ },
43
+ agents: agents.map((agent) => agent.toInfo()),
44
+ };
45
+ return c.json(response);
46
+ });
47
+ // Per-agent health endpoint
48
+ app.get('/agent/:name/health', (c) => {
49
+ const name = c.req.param('name');
50
+ const agent = registry.get(name);
51
+ if (!agent) {
52
+ return c.json({ error: `Agent not found: ${name}` }, 404);
53
+ }
54
+ const response = {
55
+ name: agent.name,
56
+ invoke: agent.hasInvoke,
57
+ chat: agent.hasChat,
58
+ };
59
+ return c.json(response);
60
+ });
61
+ // Invoke endpoint
62
+ app.post('/agent/:name/invoke', async (c) => {
63
+ const name = c.req.param('name');
64
+ const agent = registry.get(name);
65
+ if (!agent) {
66
+ return c.json({ error: `Agent not found: ${name}` }, 404);
67
+ }
68
+ // Parse and validate request
69
+ let body;
70
+ try {
71
+ body = await c.req.json();
72
+ }
73
+ catch {
74
+ return c.json({ error: 'Invalid JSON body' }, 400);
75
+ }
76
+ const parseResult = InvokeRequestSchema.safeParse(body);
77
+ if (!parseResult.success) {
78
+ const errors = parseResult.error.issues
79
+ .map((i) => `${i.path.join('.')}: ${i.message}`)
80
+ .join('; ');
81
+ return c.json({ error: `Invalid request: ${errors}` }, 400);
82
+ }
83
+ const { input, stream } = parseResult.data;
84
+ try {
85
+ const result = await agent.handleInvoke(input);
86
+ // Check if streaming
87
+ if (isAsyncGenerator(result)) {
88
+ if (stream) {
89
+ // Return SSE stream
90
+ return streamSSE(c, async (sseStream) => {
91
+ for await (const event of streamToSse(result)) {
92
+ await sseStream.writeSSE({ data: event.replace(/^data: /, '').replace(/\n\n$/, '') });
93
+ }
94
+ });
95
+ }
96
+ else {
97
+ // Collect chunks into single response
98
+ const chunks = [];
99
+ for await (const chunk of result) {
100
+ chunks.push(chunk.chunk);
101
+ }
102
+ return c.json({ output: chunks.join('') });
103
+ }
104
+ }
105
+ return c.json(result);
106
+ }
107
+ catch (err) {
108
+ return handleError(c, err);
109
+ }
110
+ });
111
+ // Chat endpoint
112
+ app.post('/agent/:name/chat', async (c) => {
113
+ const name = c.req.param('name');
114
+ const agent = registry.get(name);
115
+ if (!agent) {
116
+ return c.json({ error: `Agent not found: ${name}` }, 404);
117
+ }
118
+ // Parse and validate request
119
+ let body;
120
+ try {
121
+ body = await c.req.json();
122
+ }
123
+ catch {
124
+ return c.json({ error: 'Invalid JSON body' }, 400);
125
+ }
126
+ const parseResult = ChatRequestSchema.safeParse(body);
127
+ if (!parseResult.success) {
128
+ const errors = parseResult.error.issues
129
+ .map((i) => `${i.path.join('.')}: ${i.message}`)
130
+ .join('; ');
131
+ return c.json({ error: `Invalid request: ${errors}` }, 400);
132
+ }
133
+ const { messages, stream } = parseResult.data;
134
+ // Validate messages array is not empty
135
+ if (messages.length === 0) {
136
+ return c.json({ error: 'Messages array cannot be empty' }, 400);
137
+ }
138
+ // Validate message roles
139
+ const validRoles = ['system', 'user', 'assistant', 'tool'];
140
+ for (const msg of messages) {
141
+ if (!validRoles.includes(msg.role)) {
142
+ return c.json({ error: `Invalid role: ${msg.role}` }, 400);
143
+ }
144
+ }
145
+ try {
146
+ const result = await agent.handleChat(messages);
147
+ // Check if streaming
148
+ if (isAsyncGenerator(result)) {
149
+ if (stream) {
150
+ // Return SSE stream
151
+ return streamSSE(c, async (sseStream) => {
152
+ for await (const event of streamToSse(result)) {
153
+ await sseStream.writeSSE({ data: event.replace(/^data: /, '').replace(/\n\n$/, '') });
154
+ }
155
+ });
156
+ }
157
+ else {
158
+ // Collect chunks into single response
159
+ const chunks = [];
160
+ for await (const chunk of result) {
161
+ chunks.push(chunk.chunk);
162
+ }
163
+ return c.json({
164
+ message: { role: 'assistant', content: chunks.join('') },
165
+ });
166
+ }
167
+ }
168
+ return c.json(result);
169
+ }
170
+ catch (err) {
171
+ return handleError(c, err);
172
+ }
173
+ });
174
+ return app;
175
+ }
176
+ /**
177
+ * Check if a value is an async generator.
178
+ */
179
+ function isAsyncGenerator(value) {
180
+ return (value !== null &&
181
+ typeof value === 'object' &&
182
+ Symbol.asyncIterator in value &&
183
+ typeof value.next === 'function');
184
+ }
185
+ /**
186
+ * Handle errors from agent handlers.
187
+ */
188
+ function handleError(c, err) {
189
+ if (err instanceof NotImplementedError) {
190
+ return c.json({ error: err.message }, 501);
191
+ }
192
+ if (err instanceof AgentError) {
193
+ return c.json({ error: err.message }, 502);
194
+ }
195
+ const message = err instanceof Error ? err.message : 'Internal server error';
196
+ return c.json({ error: message }, 500);
197
+ }
198
+ /**
199
+ * Start a server hosting the provided agents.
200
+ *
201
+ * @param agents - A single agent or array of agents to serve
202
+ * @param options - Server options (host, port)
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const agent = new Agent('my-agent');
207
+ * agent.onInvoke(async (input) => ({ output: 'hello' }));
208
+ *
209
+ * serve(agent, { port: 8080 });
210
+ * // or
211
+ * serve([agent1, agent2], { port: 8080 });
212
+ * ```
213
+ */
214
+ export function serve(agents, options = {}) {
215
+ const { host = '0.0.0.0', port = 8080 } = options;
216
+ // Normalize to array
217
+ const agentList = Array.isArray(agents) ? agents : [agents];
218
+ if (agentList.length === 0) {
219
+ throw new Error('At least one agent must be provided');
220
+ }
221
+ // Check for duplicate names
222
+ const names = new Set();
223
+ for (const agent of agentList) {
224
+ if (names.has(agent.name)) {
225
+ throw new Error(`Duplicate agent name: ${agent.name}`);
226
+ }
227
+ names.add(agent.name);
228
+ }
229
+ const app = createApp(agentList);
230
+ console.log(`Starting Reminix Agent Runtime...`);
231
+ console.log(`Agents: ${agentList.map((a) => a.name).join(', ')}`);
232
+ console.log(`Listening on http://${host}:${port}`);
233
+ honoServe({
234
+ fetch: app.fetch,
235
+ hostname: host,
236
+ port,
237
+ });
238
+ }
239
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Streaming utilities for Server-Sent Events (SSE).
3
+ */
4
+ import type { StreamChunk } from './types';
5
+ /**
6
+ * Format data as an SSE event.
7
+ */
8
+ export declare function formatSseEvent(data: Record<string, unknown>): string;
9
+ /**
10
+ * Format the SSE done marker.
11
+ */
12
+ export declare function formatSseDone(): string;
13
+ /**
14
+ * Validate a streaming chunk.
15
+ *
16
+ * @param chunk - The chunk to validate
17
+ * @returns An error message if invalid, null if valid
18
+ */
19
+ export declare function validateChunk(chunk: unknown): string | null;
20
+ /**
21
+ * Convert an async generator to an SSE stream.
22
+ *
23
+ * @param generator - The async generator yielding StreamChunk objects
24
+ * @returns An async generator yielding SSE-formatted strings
25
+ */
26
+ export declare function streamToSse(generator: AsyncGenerator<StreamChunk, void, unknown>): AsyncGenerator<string, void, unknown>;
27
+ //# sourceMappingURL=streaming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;GAKG;AACH,wBAAuB,WAAW,CAChC,SAAS,EAAE,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,GACpD,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAiBvC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Streaming utilities for Server-Sent Events (SSE).
3
+ */
4
+ /**
5
+ * Format data as an SSE event.
6
+ */
7
+ export function formatSseEvent(data) {
8
+ return `data: ${JSON.stringify(data)}\n\n`;
9
+ }
10
+ /**
11
+ * Format the SSE done marker.
12
+ */
13
+ export function formatSseDone() {
14
+ return 'data: [DONE]\n\n';
15
+ }
16
+ /**
17
+ * Validate a streaming chunk.
18
+ *
19
+ * @param chunk - The chunk to validate
20
+ * @returns An error message if invalid, null if valid
21
+ */
22
+ export function validateChunk(chunk) {
23
+ if (typeof chunk !== 'object' || chunk === null) {
24
+ return 'Chunk must be an object';
25
+ }
26
+ if (!('chunk' in chunk)) {
27
+ return 'Chunk missing required "chunk" field';
28
+ }
29
+ if (typeof chunk.chunk !== 'string') {
30
+ return 'Chunk "chunk" field must be a string';
31
+ }
32
+ return null;
33
+ }
34
+ /**
35
+ * Convert an async generator to an SSE stream.
36
+ *
37
+ * @param generator - The async generator yielding StreamChunk objects
38
+ * @returns An async generator yielding SSE-formatted strings
39
+ */
40
+ export async function* streamToSse(generator) {
41
+ try {
42
+ for await (const chunk of generator) {
43
+ const error = validateChunk(chunk);
44
+ if (error) {
45
+ yield formatSseEvent({ error });
46
+ yield formatSseDone();
47
+ return;
48
+ }
49
+ yield formatSseEvent(chunk);
50
+ }
51
+ }
52
+ catch (err) {
53
+ const message = err instanceof Error ? err.message : 'Unknown error';
54
+ yield formatSseEvent({ error: `Stream error: ${message}` });
55
+ }
56
+ yield formatSseDone();
57
+ }
58
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAA6B;IAC1D,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,sCAAsC,CAAC;IAChD,CAAC;IAED,IAAI,OAAQ,KAAqB,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrD,OAAO,sCAAsC,CAAC;IAChD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,CAChC,SAAqD;IAErD,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBAChC,MAAM,aAAa,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,iBAAiB,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,aAAa,EAAE,CAAC;AACxB,CAAC"}