melony 0.2.2 → 0.2.3

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 CHANGED
@@ -14,17 +14,14 @@ npm install melony
14
14
  import { melony } from "melony";
15
15
 
16
16
  const agent = melony()
17
- .action("getWeather", async function* ({ city }: { city: string }) {
18
- yield { type: "text", data: { content: `Weather in ${city} is 24°C` } };
19
- })
20
- .on("text", async function* (event, { runtime }) {
17
+ .on("user:text", async function* (event, { runtime }) {
21
18
  if (event.data.content.includes("weather")) {
22
- yield* runtime.execute("getWeather", { city: "London" });
19
+ yield { type: "assistant:text", data: { content: "Weather in London is 24°C" } };
23
20
  }
24
21
  });
25
22
 
26
- // Run it (or use agent.stream(event) for HTTP)
27
- for await (const event of agent.build().run({ type: "text", data: { content: "How's the weather?" } })) {
23
+ // Run it (or use agent.streamResponse(event) for HTTP)
24
+ for await (const event of agent.build().run({ type: "user:text", data: { content: "How's the weather?" } })) {
28
25
  console.log(event);
29
26
  }
30
27
  ```
@@ -32,21 +29,15 @@ for await (const event of agent.build().run({ type: "text", data: { content: "Ho
32
29
  ### Legacy: Runtime Class API (Still Supported)
33
30
 
34
31
  ```ts
35
- import { MelonyRuntime } from "melony";
32
+ import { Runtime } from "melony";
36
33
 
37
34
  // 1. Create the runtime
38
- const agent = new MelonyRuntime({
39
- actions: {
40
- getWeather: {
41
- name: "getWeather",
42
- execute: async function* ({ city }: { city: string }) {
43
- yield { type: "text", data: { content: `Weather in ${city} is sunny!` } };
44
- }
45
- }
46
- },
35
+ const agent = new Runtime({
47
36
  eventHandlers: new Map([
48
- ["text", [async function* (event, { runtime }) {
49
- yield* runtime.execute("getWeather", { city: "London" });
37
+ ["user:text", [async function* (event, { runtime }) {
38
+ if (event.data.content.includes("weather")) {
39
+ yield { type: "assistant:text", data: { content: "Weather in London is sunny!" } };
40
+ }
50
41
  }]]
51
42
  ])
52
43
  });
@@ -56,46 +47,37 @@ const agent = new MelonyRuntime({
56
47
 
57
48
  The fluent builder provides an excellent developer experience with method chaining:
58
49
 
59
- ### Action Definition
60
- ```ts
61
- const agent = melony()
62
- // Register an async generator with a name
63
- .action("getWeather", async function* ({ city }) {
64
- yield { type: "text", data: { content: `Weather in ${city} is sunny!` } };
65
- });
66
- ```
67
-
68
50
  ### Event Handlers
69
51
  ```ts
70
52
  const agent = melony()
71
- .on("text", async function* (event, { runtime }) {
53
+ .on("user:text", async function* (event, { runtime }) {
72
54
  // Intercept and handle events
73
55
  if (event.data.content.includes("help")) {
74
- yield { type: "text", data: { content: "How can I help you?" } };
56
+ yield { type: "assistant:text", data: { content: "How can I help you?" } };
75
57
  }
76
58
  })
77
- .on("action:before", async function* (event) {
78
- console.log(`Executing action: ${event.data.action}`);
59
+ .on("assistant:text", async function* (event) {
60
+ console.log(`Agent said: ${event.data.content}`);
79
61
  })
80
62
  .build();
81
63
  ```
82
64
 
83
65
  ### Plugin System
84
- Plugins allow you to modularize and reuse actions and handlers across different agents. A plugin is simply a function that receives the `MelonyBuilder`.
66
+ Plugins allow you to modularize and reuse handlers across different agents. A plugin is simply a function that receives the `MelonyBuilder`.
85
67
 
86
68
  ```ts
87
69
  import { melony, MelonyPlugin } from "melony";
88
70
 
89
71
  const loggingPlugin: MelonyPlugin = (builder) => {
90
- builder.on("action:before", async function* (event) {
91
- console.log(`[Plugin] Executing: ${event.data.action}`);
72
+ builder.on("*", async function* (event) {
73
+ console.log(`[Plugin] Event: ${event.type}`);
92
74
  });
93
75
  };
94
76
 
95
77
  const agent = melony()
96
78
  .use(loggingPlugin)
97
- .action("greet", async function* () {
98
- yield { type: "text", data: { content: "Hello!" } };
79
+ .on("user:text", async function* () {
80
+ yield { type: "assistant:text", data: { content: "Hello!" } };
99
81
  });
100
82
  ```
101
83
 
@@ -103,12 +85,11 @@ const agent = melony()
103
85
  - **Full type inference** through the entire chain
104
86
  - **IntelliSense** for all methods and parameters
105
87
  - **Generic propagation** maintains type safety
106
- - **Minimalist core** with zero required dependencies (except optional Zod)
88
+ - **Minimalist core** with zero required dependencies
107
89
 
108
90
  ## Core Concepts
109
91
 
110
92
  - **Event**: The universal unit of streaming (`{ type, data, meta }`).
111
- - **Action**: An async generator that yields events.
112
93
  - **Event Handlers**: Reactive functions that listen to and emit events.
113
94
 
114
95
  ## License
package/dist/client.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { E as Event } from './generate-id-DUrFIhxI.js';
2
- export { j as generateId } from './generate-id-DUrFIhxI.js';
1
+ import { E as Event } from './generate-id-BoQwaY2G.js';
2
+ export { g as generateId } from './generate-id-BoQwaY2G.js';
3
3
 
4
4
  interface ClientState<TEvent extends Event = Event> {
5
5
  events: TEvent[];
6
- isLoading: boolean;
6
+ streaming: boolean;
7
7
  error: Error | null;
8
8
  }
9
9
  interface MelonyClientOptions<TEvent extends Event = Event> {
@@ -22,12 +22,12 @@ declare class MelonyClient<TEvent extends Event = Event> {
22
22
  subscribe(listener: (state: ClientState<TEvent>) => void): () => void;
23
23
  getState(): {
24
24
  events: TEvent[];
25
- isLoading: boolean;
25
+ streaming: boolean;
26
26
  error: Error | null;
27
27
  };
28
28
  private getRequestHeaders;
29
29
  private setState;
30
- sendEvent(event: TEvent): AsyncGenerator<TEvent>;
30
+ send(event: TEvent): AsyncGenerator<TEvent>;
31
31
  private handleIncomingEvent;
32
32
  reset(events?: TEvent[]): void;
33
33
  }
package/dist/client.js CHANGED
@@ -1,4 +1,3 @@
1
- import { generateId } from './chunk-WAI5H335.js';
2
1
  export { generateId } from './chunk-WAI5H335.js';
3
2
 
4
3
  // src/client.ts
@@ -11,7 +10,7 @@ var MelonyClient = class {
11
10
  this.headers = options.headers;
12
11
  this.state = {
13
12
  events: options.initialEvents ?? [],
14
- isLoading: false,
13
+ streaming: false,
15
14
  error: null
16
15
  };
17
16
  }
@@ -38,24 +37,14 @@ var MelonyClient = class {
38
37
  this.state = { ...this.state, ...updates };
39
38
  this.stateListeners.forEach((l) => l(this.getState()));
40
39
  }
41
- async *sendEvent(event) {
40
+ async *send(event) {
42
41
  if (this.abortController) this.abortController.abort();
43
42
  this.abortController = new AbortController();
44
- const runId = event.meta?.runId ?? generateId();
45
- const state = event.meta?.state ?? this.lastServerState;
46
43
  const optimisticEvent = {
47
- ...event,
48
- meta: {
49
- ...event.meta,
50
- id: event.meta?.id ?? generateId(),
51
- runId,
52
- state,
53
- role: event.meta?.role ?? "user",
54
- timestamp: event.meta?.timestamp ?? Date.now()
55
- }
44
+ ...event
56
45
  };
57
46
  this.setState({
58
- isLoading: true,
47
+ streaming: true,
59
48
  error: null,
60
49
  events: [...this.state.events, optimisticEvent]
61
50
  });
@@ -90,21 +79,18 @@ var MelonyClient = class {
90
79
  }
91
80
  }
92
81
  }
93
- this.setState({ isLoading: false });
82
+ this.setState({ streaming: false });
94
83
  } catch (err) {
95
84
  if (err instanceof Error && err.name === "AbortError") {
96
- this.setState({ isLoading: false });
85
+ this.setState({ streaming: false });
97
86
  return;
98
87
  }
99
88
  const error = err instanceof Error ? err : new Error(String(err));
100
- this.setState({ error, isLoading: false });
89
+ this.setState({ error, streaming: false });
101
90
  throw error;
102
91
  }
103
92
  }
104
93
  handleIncomingEvent(event) {
105
- if (event.meta?.state) {
106
- this.lastServerState = event.meta.state;
107
- }
108
94
  const events = [...this.state.events];
109
95
  events.push(event);
110
96
  this.setState({ events });
@@ -114,7 +100,7 @@ var MelonyClient = class {
114
100
  this.setState({
115
101
  events,
116
102
  error: null,
117
- isLoading: false
103
+ streaming: false
118
104
  });
119
105
  }
120
106
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["import { Event } from \"./types\";\nimport { generateId } from \"./utils/generate-id\";\n\nexport type { Event };\nexport { generateId };\n\nexport interface ClientState<TEvent extends Event = Event> {\n events: TEvent[];\n isLoading: boolean;\n error: Error | null;\n}\n\nexport interface MelonyClientOptions<TEvent extends Event = Event> {\n url: string;\n initialEvents?: TEvent[];\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n}\n\nexport class MelonyClient<TEvent extends Event = Event> {\n private state: ClientState<TEvent>;\n public readonly url: string;\n private headers?: MelonyClientOptions<TEvent>[\"headers\"];\n private lastServerState: any = null;\n private abortController: AbortController | null = null;\n private stateListeners: Set<(state: ClientState<TEvent>) => void> = new Set();\n\n constructor(options: MelonyClientOptions<TEvent>) {\n this.url = options.url;\n this.headers = options.headers;\n this.state = {\n events: options.initialEvents ?? [],\n isLoading: false,\n error: null,\n };\n }\n\n subscribe(listener: (state: ClientState<TEvent>) => void) {\n this.stateListeners.add(listener);\n return () => {\n this.stateListeners.delete(listener);\n };\n }\n\n getState() {\n return { ...this.state };\n }\n\n private async getRequestHeaders() {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (this.headers) {\n const extraHeaders =\n typeof this.headers === \"function\"\n ? await this.headers()\n : this.headers;\n Object.assign(headers, extraHeaders);\n }\n return headers;\n }\n\n private setState(updates: Partial<ClientState<TEvent>>) {\n this.state = { ...this.state, ...updates };\n this.stateListeners.forEach((l) => l(this.getState()));\n }\n\n async *sendEvent(event: TEvent): AsyncGenerator<TEvent> {\n if (this.abortController) this.abortController.abort();\n this.abortController = new AbortController();\n\n const runId = event.meta?.runId ?? generateId();\n\n // if the state comes from the client, no last server state is preserved\n const state = event.meta?.state ?? this.lastServerState;\n\n const optimisticEvent: TEvent = {\n ...event,\n meta: {\n ...event.meta,\n id: event.meta?.id ?? generateId(),\n runId,\n state,\n role: event.meta?.role ?? \"user\",\n timestamp: event.meta?.timestamp ?? Date.now(),\n },\n } as TEvent;\n\n this.setState({\n isLoading: true,\n error: null,\n events: [...this.state.events, optimisticEvent],\n });\n\n try {\n const headers = await this.getRequestHeaders();\n const response = await fetch(this.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ event: optimisticEvent }),\n signal: this.abortController.signal,\n });\n\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n if (!response.body) throw new Error(\"No response body\");\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n try {\n const incomingEvent: TEvent = JSON.parse(line.slice(6));\n this.handleIncomingEvent(incomingEvent);\n yield incomingEvent;\n } catch (e) {\n console.error(\"Failed to parse event\", e);\n }\n }\n }\n this.setState({ isLoading: false });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n this.setState({ isLoading: false });\n return;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n this.setState({ error, isLoading: false });\n throw error;\n }\n }\n\n private handleIncomingEvent(event: TEvent) {\n if (event.meta?.state) {\n this.lastServerState = event.meta.state;\n }\n\n const events = [...this.state.events];\n\n events.push(event);\n\n this.setState({ events });\n }\n\n reset(events: TEvent[] = []) {\n if (this.abortController) this.abortController.abort();\n this.setState({\n events,\n error: null,\n isLoading: false,\n });\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["import { Event } from \"./types\";\nimport { generateId } from \"./utils/generate-id\";\n\nexport type { Event };\nexport { generateId };\n\nexport interface ClientState<TEvent extends Event = Event> {\n events: TEvent[];\n streaming: boolean;\n error: Error | null;\n}\n\nexport interface MelonyClientOptions<TEvent extends Event = Event> {\n url: string;\n initialEvents?: TEvent[];\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n}\n\nexport class MelonyClient<TEvent extends Event = Event> {\n private state: ClientState<TEvent>;\n public readonly url: string;\n private headers?: MelonyClientOptions<TEvent>[\"headers\"];\n private lastServerState: any = null;\n private abortController: AbortController | null = null;\n private stateListeners: Set<(state: ClientState<TEvent>) => void> = new Set();\n\n constructor(options: MelonyClientOptions<TEvent>) {\n this.url = options.url;\n this.headers = options.headers;\n this.state = {\n events: options.initialEvents ?? [],\n streaming: false,\n error: null,\n };\n }\n\n subscribe(listener: (state: ClientState<TEvent>) => void) {\n this.stateListeners.add(listener);\n return () => {\n this.stateListeners.delete(listener);\n };\n }\n\n getState() {\n return { ...this.state };\n }\n\n private async getRequestHeaders() {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (this.headers) {\n const extraHeaders =\n typeof this.headers === \"function\"\n ? await this.headers()\n : this.headers;\n Object.assign(headers, extraHeaders);\n }\n return headers;\n }\n\n private setState(updates: Partial<ClientState<TEvent>>) {\n this.state = { ...this.state, ...updates };\n this.stateListeners.forEach((l) => l(this.getState()));\n }\n\n async *send(event: TEvent): AsyncGenerator<TEvent> {\n if (this.abortController) this.abortController.abort();\n this.abortController = new AbortController();\n\n const optimisticEvent: TEvent = {\n ...event\n } as TEvent;\n\n this.setState({\n streaming: true,\n error: null,\n events: [...this.state.events, optimisticEvent],\n });\n\n try {\n const headers = await this.getRequestHeaders();\n const response = await fetch(this.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ event: optimisticEvent }),\n signal: this.abortController.signal,\n });\n\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n if (!response.body) throw new Error(\"No response body\");\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n try {\n const incomingEvent: TEvent = JSON.parse(line.slice(6));\n this.handleIncomingEvent(incomingEvent);\n yield incomingEvent;\n } catch (e) {\n console.error(\"Failed to parse event\", e);\n }\n }\n }\n this.setState({ streaming: false });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n this.setState({ streaming: false });\n return;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n this.setState({ error, streaming: false });\n throw error;\n }\n }\n\n private handleIncomingEvent(event: TEvent) {\n const events = [...this.state.events];\n\n events.push(event);\n\n this.setState({ events });\n }\n\n reset(events: TEvent[] = []) {\n if (this.abortController) this.abortController.abort();\n this.setState({\n events,\n error: null,\n streaming: false,\n });\n }\n}\n"]}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The Melony Runtime.
3
+ * Fully unopinionated - processes events through handlers.
4
+ */
5
+ declare class Runtime<TState = any, TEvent extends Event = Event> {
6
+ readonly config: Config<TState, TEvent>;
7
+ private queue;
8
+ private isEmitting;
9
+ constructor(config: Config<TState, TEvent>);
10
+ /**
11
+ * Process an incoming event through the runtime.
12
+ * All event processing is handled by user-defined event handlers.
13
+ */
14
+ run(event: TEvent, options?: {
15
+ state?: TState;
16
+ runId?: string;
17
+ }): AsyncGenerator<TEvent>;
18
+ /**
19
+ * Run all event handlers that match the given event type.
20
+ */
21
+ private runEventHandlers;
22
+ /**
23
+ * Internal helper to yield an event with metadata.
24
+ */
25
+ private emit;
26
+ }
27
+
28
+ /**
29
+ * The core Event structure.
30
+ * Fully unopinionated - just type, data, and optional metadata.
31
+ */
32
+ type Event<TData = any> = {
33
+ type: string;
34
+ data: TData;
35
+ };
36
+ /**
37
+ * Built-in error event emitted by the runtime.
38
+ */
39
+ interface ErrorEvent extends Event<{
40
+ message: string;
41
+ stack?: string;
42
+ }> {
43
+ type: "error";
44
+ }
45
+ interface RuntimeContext<TState = any, TEvent extends Event = Event> {
46
+ state: TState;
47
+ runId: string;
48
+ runtime: Runtime<TState, TEvent>;
49
+ /**
50
+ * Immediately interrupts the runtime execution.
51
+ * If an event is provided, it will be emitted before the runtime stops.
52
+ */
53
+ suspend: (event?: TEvent) => never;
54
+ }
55
+ /**
56
+ * Event handler function for processing events.
57
+ * Can return events to emit or undefined to continue processing.
58
+ */
59
+ type EventHandler<TState = any, TEvent extends Event = Event> = (event: TEvent, context?: RuntimeContext<TState, TEvent>) => AsyncGenerator<TEvent, void, unknown> | void;
60
+ interface Config<TState = any, TEvent extends Event = Event> {
61
+ eventHandlers: Map<string, EventHandler<TState, TEvent>[]>;
62
+ }
63
+
64
+ declare const generateId: () => string;
65
+
66
+ export { type Config as C, type Event as E, Runtime as R, type RuntimeContext as a, type ErrorEvent as b, type EventHandler as c, generateId as g };
package/dist/index.d.ts CHANGED
@@ -1,42 +1,20 @@
1
- import { R as Runtime, A as ActionExecute, a as Action, E as Event, C as Config, b as RuntimeContext } from './generate-id-DUrFIhxI.js';
2
- export { f as ActionAfterEvent, e as ActionBeforeEvent, g as CallActionEvent, h as ErrorEvent, i as EventHandler, d as EventMeta, c as Role, j as generateId } from './generate-id-DUrFIhxI.js';
1
+ import { R as Runtime, E as Event, C as Config, a as RuntimeContext } from './generate-id-BoQwaY2G.js';
2
+ export { b as ErrorEvent, c as EventHandler, g as generateId } from './generate-id-BoQwaY2G.js';
3
3
 
4
4
  declare const MelonyRuntime: typeof Runtime;
5
5
 
6
- /**
7
- * Create an action with just a name and handler.
8
- * Compatible with any agent - types are resolved automatically when added to an agent.
9
- */
10
- declare function action<TParams = any>(name: string, execute: ActionExecute<TParams, any, any>): Action<TParams, any, any>;
11
- /**
12
- * Helper to define an action with full type inference (for advanced use cases).
13
- */
14
- declare function action<TParams = any, TState = any, TEvent extends Event = Event>(config: Action<TParams, TState, TEvent>): Action<TParams, TState, TEvent>;
15
-
16
6
  /**
17
7
  * A Melony plugin is a function that receives the builder and extends it.
18
- * This allows for modularizing common actions and handlers.
8
+ * This allows for modularizing common handlers.
19
9
  */
20
10
  type MelonyPlugin<TState = any, TEvent extends Event = Event> = (builder: MelonyBuilder<TState, TEvent>) => void;
21
11
  /**
22
12
  * Fluent builder for creating Melony agents with excellent developer experience.
23
- * Provides method chaining for actions and plugins with full TypeScript support.
13
+ * Provides method chaining for handlers and plugins with full TypeScript support.
24
14
  */
25
15
  declare class MelonyBuilder<TState = any, TEvent extends Event = Event> {
26
16
  private config;
27
17
  constructor(initialConfig?: Partial<Config<TState, TEvent>>);
28
- /**
29
- * Add built-in event handlers that are available in all agents.
30
- */
31
- private addBuiltInHandlers;
32
- /**
33
- * Add an action to the agent with fluent method chaining.
34
- * Supports two patterns:
35
- * - Pass a pre-defined Action object
36
- * - Define action inline with name and handler
37
- */
38
- action<TParams = any>(action: Action<TParams, any, any>): this;
39
- action<TParams = any>(name: string, execute: ActionExecute<TParams, any, any>): this;
40
18
  /**
41
19
  * Add an event handler for a specific event type. Supports method chaining.
42
20
  * The handler receives the narrowed event type based on the eventType string.
@@ -46,7 +24,7 @@ declare class MelonyBuilder<TState = any, TEvent extends Event = Event> {
46
24
  }>, context: RuntimeContext<TState, TEvent>) => AsyncGenerator<TEvent, void, unknown> | void): this;
47
25
  /**
48
26
  * Use a plugin to extend the builder.
49
- * This is ideal for modularizing common actions and handlers.
27
+ * This is ideal for modularizing common handlers.
50
28
  */
51
29
  use(plugin: MelonyPlugin<TState, TEvent>): this;
52
30
  /**
@@ -58,8 +36,9 @@ declare class MelonyBuilder<TState = any, TEvent extends Event = Event> {
58
36
  * Execute and stream the response for an event.
59
37
  * This is a convenience method that builds the runtime and calls run().
60
38
  */
61
- stream(event: TEvent, options?: {
39
+ streamResponse(event: TEvent, options?: {
62
40
  state?: TState;
41
+ runId?: string;
63
42
  }): Promise<Response>;
64
43
  /**
65
44
  * Get the current configuration (useful for debugging or serialization).
@@ -78,4 +57,4 @@ declare function melony<TState = any, TEvent extends Event = Event>(initialConfi
78
57
  */
79
58
  declare function createStreamResponse(generator: AsyncGenerator<Event>): Response;
80
59
 
81
- export { Action, ActionExecute, Config, Event, MelonyBuilder, type MelonyPlugin, MelonyRuntime, Runtime, RuntimeContext, action, createStreamResponse, melony };
60
+ export { Config, Event, MelonyBuilder, type MelonyPlugin, MelonyRuntime, Runtime, RuntimeContext, createStreamResponse, melony };
package/dist/index.js CHANGED
@@ -11,87 +11,16 @@ var Runtime = class {
11
11
  this.isEmitting = false;
12
12
  this.config = config;
13
13
  }
14
- /**
15
- * Run an action by name with given params.
16
- * This is the primary way to execute actions.
17
- */
18
- async *execute(actionName, params, options) {
19
- const runId = options?.runId ?? generateId();
20
- const context = {
21
- state: options?.state ?? {},
22
- runtime: this,
23
- runId,
24
- actions: this.config.actions,
25
- suspend: (event) => {
26
- throw event || { type: "run-suspended", data: {} };
27
- }
28
- };
29
- const action2 = this.config.actions[actionName];
30
- if (!action2) {
31
- yield* this.emit(
32
- {
33
- type: "error",
34
- data: { message: `Action "${actionName}" not found` }
35
- },
36
- context
37
- );
38
- return;
39
- }
40
- try {
41
- yield* this.emit(
42
- {
43
- type: "action:before",
44
- data: { action: actionName, params }
45
- },
46
- context
47
- );
48
- const generator = action2.execute(params, context);
49
- let result = void 0;
50
- while (true) {
51
- const { value, done } = await generator.next();
52
- if (done) {
53
- result = value;
54
- break;
55
- }
56
- yield* this.emit(value, context);
57
- }
58
- yield* this.emit(
59
- {
60
- type: "action:after",
61
- data: { action: actionName, result }
62
- },
63
- context
64
- );
65
- } catch (error) {
66
- let eventToEmit;
67
- if (isEvent(error)) {
68
- eventToEmit = error;
69
- } else {
70
- eventToEmit = {
71
- type: "error",
72
- data: {
73
- action: actionName,
74
- message: error instanceof Error ? error.message : String(error),
75
- stack: error instanceof Error ? error.stack : void 0
76
- }
77
- };
78
- }
79
- if (eventToEmit) {
80
- yield* this.emit(eventToEmit, context);
81
- }
82
- }
83
- }
84
14
  /**
85
15
  * Process an incoming event through the runtime.
86
16
  * All event processing is handled by user-defined event handlers.
87
17
  */
88
- async *run(event) {
89
- const runId = event.meta?.runId ?? generateId();
18
+ async *run(event, options) {
19
+ const runId = options?.runId ?? generateId();
90
20
  const context = {
91
- state: event.meta?.state ?? {},
21
+ state: options?.state ?? {},
92
22
  runtime: this,
93
23
  runId,
94
- actions: this.config.actions,
95
24
  suspend: (event2) => {
96
25
  throw event2 || { type: "run-suspended", data: {} };
97
26
  }
@@ -120,12 +49,15 @@ var Runtime = class {
120
49
  * Run all event handlers that match the given event type.
121
50
  */
122
51
  async *runEventHandlers(event, context) {
123
- const handlers = this.config.eventHandlers.get(event.type) || [];
52
+ const handlers = [
53
+ ...this.config.eventHandlers.get(event.type) || [],
54
+ ...this.config.eventHandlers.get("*") || []
55
+ ];
56
+ yield* this.emit(event, context);
124
57
  for (const handler of handlers) {
125
58
  const result = handler(event, context);
126
59
  if (result) {
127
60
  for await (const yieldedEvent of result) {
128
- yield yieldedEvent;
129
61
  yield* this.runEventHandlers(yieldedEvent, context);
130
62
  }
131
63
  }
@@ -133,7 +65,6 @@ var Runtime = class {
133
65
  }
134
66
  /**
135
67
  * Internal helper to yield an event with metadata.
136
- * Handlers are invoked by runEventHandlers when events bubble up.
137
68
  */
138
69
  async *emit(event, context) {
139
70
  this.queue.push(event);
@@ -142,19 +73,7 @@ var Runtime = class {
142
73
  try {
143
74
  while (this.queue.length > 0) {
144
75
  const current = this.queue.shift();
145
- const finalEvent = {
146
- ...current,
147
- meta: {
148
- ...current.meta,
149
- id: current.meta?.id ?? generateId(),
150
- runtime: this,
151
- runId: context.runId,
152
- timestamp: current.meta?.timestamp ?? Date.now(),
153
- role: current.meta?.role ?? "assistant",
154
- state: context.state
155
- }
156
- };
157
- yield finalEvent;
76
+ yield current;
158
77
  }
159
78
  } finally {
160
79
  this.isEmitting = false;
@@ -165,18 +84,6 @@ var Runtime = class {
165
84
  // src/melony.ts
166
85
  var MelonyRuntime = Runtime;
167
86
 
168
- // src/action.ts
169
- function action(...args) {
170
- if (typeof args[0] === "string") {
171
- const [name, execute] = args;
172
- return { name, execute };
173
- }
174
- if (typeof args[0] === "object" && args[0] !== null && "name" in args[0] && "execute" in args[0]) {
175
- return args[0];
176
- }
177
- throw new Error("Invalid action parameters");
178
- }
179
-
180
87
  // src/utils/create-stream-response.ts
181
88
  function createStreamResponse(generator) {
182
89
  const encoder = new TextEncoder();
@@ -208,37 +115,8 @@ function createStreamResponse(generator) {
208
115
  var MelonyBuilder = class {
209
116
  constructor(initialConfig) {
210
117
  this.config = {
211
- actions: {},
212
- eventHandlers: /* @__PURE__ */ new Map(),
213
- ...initialConfig
118
+ eventHandlers: initialConfig?.eventHandlers ?? /* @__PURE__ */ new Map()
214
119
  };
215
- this.addBuiltInHandlers();
216
- }
217
- /**
218
- * Add built-in event handlers that are available in all agents.
219
- */
220
- addBuiltInHandlers() {
221
- this.on("call-action", async function* (event, context) {
222
- const { action: actionName, params } = event.data;
223
- yield* context.runtime.execute(actionName, params);
224
- });
225
- }
226
- action(nameOrAction, execute) {
227
- if (typeof nameOrAction !== "string") {
228
- const typedAction = {
229
- name: nameOrAction.name,
230
- execute: nameOrAction.execute
231
- };
232
- this.config.actions[nameOrAction.name] = typedAction;
233
- return this;
234
- }
235
- const name = nameOrAction;
236
- const actionObj = {
237
- name,
238
- execute
239
- };
240
- this.config.actions[name] = actionObj;
241
- return this;
242
120
  }
243
121
  /**
244
122
  * Add an event handler for a specific event type. Supports method chaining.
@@ -253,7 +131,7 @@ var MelonyBuilder = class {
253
131
  }
254
132
  /**
255
133
  * Use a plugin to extend the builder.
256
- * This is ideal for modularizing common actions and handlers.
134
+ * This is ideal for modularizing common handlers.
257
135
  */
258
136
  use(plugin) {
259
137
  plugin(this);
@@ -270,9 +148,9 @@ var MelonyBuilder = class {
270
148
  * Execute and stream the response for an event.
271
149
  * This is a convenience method that builds the runtime and calls run().
272
150
  */
273
- async stream(event, options) {
151
+ async streamResponse(event, options) {
274
152
  const runtime = this.build();
275
- const generator = runtime.run(event);
153
+ const generator = runtime.run(event, options);
276
154
  return createStreamResponse(generator);
277
155
  }
278
156
  /**
@@ -286,6 +164,6 @@ function melony(initialConfig) {
286
164
  return new MelonyBuilder(initialConfig);
287
165
  }
288
166
 
289
- export { MelonyBuilder, MelonyRuntime, Runtime, action, createStreamResponse, melony };
167
+ export { MelonyBuilder, MelonyRuntime, Runtime, createStreamResponse, melony };
290
168
  //# sourceMappingURL=index.js.map
291
169
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime.ts","../src/melony.ts","../src/action.ts","../src/utils/create-stream-response.ts","../src/builder.ts"],"names":["action","event"],"mappings":"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","file":"index.js","sourcesContent":["import {\n Action,\n Event,\n RuntimeContext,\n Config,\n EventHandler,\n} from \"./types\";\nimport { generateId } from \"./utils/generate-id\";\n\n/**\n * Helper to check if a value is a Melony Event.\n */\nfunction isEvent(val: any): val is Event {\n return val && typeof val === \"object\" && typeof val.type === \"string\";\n}\n\n/**\n * The Melony Runtime.\n * Fully unopinionated - executes a single action per run.\n * Chaining/looping is left to userland.\n */\nexport class Runtime<TState = any, TEvent extends Event = Event> {\n public readonly config: Config<TState, TEvent>;\n private queue: TEvent[] = [];\n private isEmitting = false;\n\n constructor(config: Config<TState, TEvent>) {\n this.config = config;\n }\n\n /**\n * Run an action by name with given params.\n * This is the primary way to execute actions.\n */\n public async *execute(\n actionName: string,\n params: any,\n options?: { state?: TState; runId?: string },\n ): AsyncGenerator<TEvent> {\n const runId = options?.runId ?? generateId();\n\n const context: RuntimeContext<TState, TEvent> = {\n state: (options?.state ?? {}) as TState,\n runtime: this,\n runId,\n actions: this.config.actions,\n suspend: (event?: TEvent) => {\n throw event || { type: \"run-suspended\", data: {} };\n },\n };\n\n const action = this.config.actions[actionName];\n if (!action) {\n yield* this.emit(\n {\n type: \"error\",\n data: { message: `Action \"${actionName}\" not found` },\n } as TEvent,\n context,\n );\n return;\n }\n\n try {\n // Emit action:before event\n yield* this.emit(\n {\n type: \"action:before\",\n data: { action: actionName, params },\n } as TEvent,\n context,\n );\n\n // Execute the action - users handle lifecycle events explicitly\n const generator = action.execute(params, context);\n let result: any = undefined;\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) {\n result = value; // Capture the return value\n break;\n }\n yield* this.emit(value as TEvent, context);\n }\n\n // Emit action:after event\n yield* this.emit(\n {\n type: \"action:after\",\n data: { action: actionName, result },\n } as TEvent,\n context,\n );\n } catch (error) {\n let eventToEmit: TEvent | undefined;\n\n if (isEvent(error)) {\n eventToEmit = error as TEvent;\n } else {\n eventToEmit = {\n type: \"error\",\n data: {\n action: actionName,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n } as TEvent;\n }\n\n if (eventToEmit) {\n yield* this.emit(eventToEmit, context);\n }\n }\n }\n\n /**\n * Process an incoming event through the runtime.\n * All event processing is handled by user-defined event handlers.\n */\n public async *run(event: TEvent): AsyncGenerator<TEvent> {\n const runId = event.meta?.runId ?? generateId();\n\n const context: RuntimeContext<TState, TEvent> = {\n state: (event.meta?.state ?? {}) as TState,\n runtime: this,\n runId,\n actions: this.config.actions,\n suspend: (event?: TEvent) => {\n throw event || { type: \"run-suspended\", data: {} };\n },\n };\n\n try {\n // Process the incoming event through handlers\n yield* this.runEventHandlers(event, context);\n } catch (error) {\n let eventToEmit: TEvent | undefined;\n\n if (isEvent(error)) {\n eventToEmit = error as TEvent;\n } else {\n eventToEmit = {\n type: \"error\",\n data: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n } as TEvent;\n }\n\n if (eventToEmit) {\n yield* this.emit(eventToEmit, context);\n }\n }\n }\n\n\n /**\n * Run all event handlers that match the given event type.\n */\n private async *runEventHandlers(\n event: TEvent,\n context: RuntimeContext<TState, TEvent>,\n ): AsyncGenerator<TEvent> {\n const handlers = this.config.eventHandlers.get(event.type) || [];\n for (const handler of handlers) {\n const result = handler(event, context);\n if (result) {\n for await (const yieldedEvent of result) {\n yield yieldedEvent;\n // Recursively process yielded events through their handlers\n yield* this.runEventHandlers(yieldedEvent, context);\n }\n }\n }\n }\n\n /**\n * Internal helper to yield an event with metadata.\n * Handlers are invoked by runEventHandlers when events bubble up.\n */\n private async *emit(\n event: TEvent,\n context: RuntimeContext<TState, TEvent>,\n ): AsyncGenerator<TEvent> {\n this.queue.push(event);\n\n if (this.isEmitting) return;\n\n this.isEmitting = true;\n try {\n while (this.queue.length > 0) {\n const current = this.queue.shift()!;\n\n const finalEvent: TEvent = {\n ...current,\n meta: {\n ...current.meta,\n id: current.meta?.id ?? generateId(), \n runtime: this,\n runId: context.runId,\n timestamp: current.meta?.timestamp ?? Date.now(),\n role: current.meta?.role ?? \"assistant\",\n state: context.state,\n },\n };\n\n yield finalEvent;\n }\n } finally {\n this.isEmitting = false;\n }\n }\n}\n","import { Runtime } from \"./runtime\";\n\nexport const MelonyRuntime = Runtime;"," import { Action, ActionExecute, Event } from \"./types\";\n\n/**\n * Create an action with just a name and handler.\n * Compatible with any agent - types are resolved automatically when added to an agent.\n */\nexport function action<TParams = any>(\n name: string,\n execute: ActionExecute<TParams, any, any>,\n): Action<TParams, any, any>;\n/**\n * Helper to define an action with full type inference (for advanced use cases).\n */\nexport function action<\n TParams = any,\n TState = any,\n TEvent extends Event = Event,\n>(\n config: Action<TParams, TState, TEvent>,\n): Action<TParams, TState, TEvent>;\nexport function action<\n TParams = any,\n TState = any,\n TEvent extends Event = Event,\n>(\n ...args: [Action<TParams, TState, TEvent>] | [string, ActionExecute<TParams, any, any>]\n): Action<TParams, TState, TEvent> | Action<TParams, any, any> {\n if (typeof args[0] === \"string\") {\n const [name, execute] = args as [string, ActionExecute<TParams, any, any>];\n return { name, execute };\n }\n\n if (typeof args[0] === \"object\" && args[0] !== null && 'name' in args[0] && 'execute' in args[0]) {\n return args[0] as Action<TParams, TState, TEvent>;\n }\n\n throw new Error(\"Invalid action parameters\");\n}\n","import { Event } from \"../types\";\n\n/**\n * Convert an async generator of events to an HTTP streaming response\n * Exported for backward compatibility and standalone usage\n */\nexport function createStreamResponse(\n generator: AsyncGenerator<Event>,\n): Response {\n const encoder = new TextEncoder();\n const stream = new ReadableStream({\n async start(controller) {\n try {\n for await (const message of generator) {\n // Format as SSE: data: {...}\\n\\n\n const chunk = `data: ${JSON.stringify(message)}\\n\\n`;\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n","import {\n Action,\n Event,\n EventHandler,\n Config,\n ActionExecute,\n RuntimeContext,\n} from \"./types\";\nimport { Runtime } from \"./runtime\";\nimport { createStreamResponse } from \"./utils/create-stream-response\";\n\n/**\n * A Melony plugin is a function that receives the builder and extends it.\n * This allows for modularizing common actions and handlers.\n */\nexport type MelonyPlugin<TState = any, TEvent extends Event = Event> = (\n builder: MelonyBuilder<TState, TEvent>\n) => void;\n\n/**\n * Fluent builder for creating Melony agents with excellent developer experience.\n * Provides method chaining for actions and plugins with full TypeScript support.\n */\nexport class MelonyBuilder<\n TState = any,\n TEvent extends Event = Event\n> {\n private config: Config<TState, TEvent>;\n\n constructor(initialConfig?: Partial<Config<TState, TEvent>>) {\n this.config = {\n actions: {},\n eventHandlers: new Map(),\n ...initialConfig,\n };\n\n // Add built-in call-action handler\n this.addBuiltInHandlers();\n }\n\n /**\n * Add built-in event handlers that are available in all agents.\n */\n private addBuiltInHandlers(): void {\n // Built-in call-action handler\n this.on(\"call-action\", async function* (event, context) {\n const { action: actionName, params } = event.data as { action: string; params: unknown };\n\n // Execute the action (runtime will automatically emit action:before and action:after events)\n yield* context.runtime.execute(actionName, params);\n });\n }\n\n /**\n * Add an action to the agent with fluent method chaining.\n * Supports two patterns:\n * - Pass a pre-defined Action object\n * - Define action inline with name and handler\n */\n action<TParams = any>(\n action: Action<TParams, any, any>\n ): this;\n action<TParams = any>(\n name: string,\n execute: ActionExecute<TParams, any, any>\n ): this;\n action<TParams = any>(\n nameOrAction: string | Action<TParams, any, any>,\n execute?: ActionExecute<TParams, any, any>\n ): this {\n if (typeof nameOrAction !== 'string') {\n // Called as: .action(action) - pre-defined action object\n // Auto-cast to agent types for better DX\n const typedAction: Action<TParams, TState, TEvent> = {\n name: nameOrAction.name,\n execute: nameOrAction.execute as ActionExecute<TParams, TState, TEvent>,\n };\n this.config.actions[nameOrAction.name] = typedAction;\n return this;\n }\n\n // Called as: .action(name, execute)\n const name = nameOrAction;\n const actionObj: Action<TParams, TState, TEvent> = {\n name,\n execute: execute! as ActionExecute<TParams, TState, TEvent>,\n };\n this.config.actions[name] = actionObj;\n return this;\n }\n\n\n /**\n * Add an event handler for a specific event type. Supports method chaining.\n * The handler receives the narrowed event type based on the eventType string.\n */\n on<K extends TEvent[\"type\"]>(\n eventType: K,\n handler: (\n event: Extract<TEvent, { type: K }>,\n context: RuntimeContext<TState, TEvent>\n ) => AsyncGenerator<TEvent, void, unknown> | void\n ): this {\n if (!this.config.eventHandlers.has(eventType)) {\n this.config.eventHandlers.set(eventType, []);\n }\n // Cast is safe because runtime only calls this handler for matching event types\n this.config.eventHandlers.get(eventType)!.push(handler as EventHandler<TState, TEvent>);\n return this;\n }\n\n /**\n * Use a plugin to extend the builder.\n * This is ideal for modularizing common actions and handlers.\n */\n use(plugin: MelonyPlugin<TState, TEvent>): this {\n plugin(this);\n return this;\n }\n\n /**\n * Build and return the Melony runtime instance.\n * This is the final method in the fluent chain.\n */\n build(): Runtime<TState, TEvent> {\n return new Runtime(this.config);\n }\n\n /**\n * Execute and stream the response for an event.\n * This is a convenience method that builds the runtime and calls run().\n */\n async stream(\n event: TEvent,\n options?: { state?: TState }\n ): Promise<Response> {\n const runtime = this.build();\n const generator = runtime.run(event);\n return createStreamResponse(generator);\n }\n\n /**\n * Get the current configuration (useful for debugging or serialization).\n */\n getConfig(): Config<TState, TEvent> {\n return { ...this.config };\n }\n}\n\n/**\n * Factory function to create a new Melony builder instance.\n * This is the entry point for the fluent API.\n */\nexport function melony<\n TState = any,\n TEvent extends Event = Event\n>(initialConfig?: Partial<Config<TState, TEvent>>): MelonyBuilder<TState, TEvent> {\n return new MelonyBuilder<TState, TEvent>(initialConfig);\n}"]}
1
+ {"version":3,"sources":["../src/runtime.ts","../src/melony.ts","../src/utils/create-stream-response.ts","../src/builder.ts"],"names":["event"],"mappings":"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","file":"index.js","sourcesContent":["import {\n Event,\n RuntimeContext,\n Config,\n} from \"./types\";\nimport { generateId } from \"./utils/generate-id\";\n\n/**\n * Helper to check if a value is a Melony Event.\n */\nfunction isEvent(val: any): val is Event {\n return val && typeof val === \"object\" && typeof val.type === \"string\";\n}\n\n/**\n * The Melony Runtime.\n * Fully unopinionated - processes events through handlers.\n */\nexport class Runtime<TState = any, TEvent extends Event = Event> {\n public readonly config: Config<TState, TEvent>;\n private queue: TEvent[] = [];\n private isEmitting = false;\n\n constructor(config: Config<TState, TEvent>) {\n this.config = config;\n }\n\n /**\n * Process an incoming event through the runtime.\n * All event processing is handled by user-defined event handlers.\n */\n public async *run(\n event: TEvent, \n options?: { state?: TState; runId?: string }\n ): AsyncGenerator<TEvent> {\n const runId = options?.runId ?? generateId();\n \n const context: RuntimeContext<TState, TEvent> = {\n state: (options?.state ?? {}) as TState,\n runtime: this,\n runId,\n suspend: (event?: TEvent) => {\n throw event || { type: \"run-suspended\", data: {} };\n },\n };\n\n try {\n // Process the incoming event through handlers\n yield* this.runEventHandlers(event, context);\n } catch (error) {\n let eventToEmit: TEvent | undefined;\n\n if (isEvent(error)) {\n eventToEmit = error as TEvent;\n } else {\n eventToEmit = {\n type: \"error\",\n data: {\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n } as TEvent;\n }\n\n if (eventToEmit) {\n yield* this.emit(eventToEmit, context);\n }\n }\n }\n\n\n /**\n * Run all event handlers that match the given event type.\n */\n private async *runEventHandlers(\n event: TEvent,\n context?: RuntimeContext<TState, TEvent>,\n ): AsyncGenerator<TEvent> {\n const handlers = [\n ...(this.config.eventHandlers.get(event.type) || []),\n ...(this.config.eventHandlers.get(\"*\") || []),\n ];\n \n // First emit the event itself\n yield* this.emit(event, context);\n\n for (const handler of handlers) {\n const result = handler(event, context);\n if (result) {\n for await (const yieldedEvent of result) {\n // Recursively process yielded events through their handlers\n yield* this.runEventHandlers(yieldedEvent, context);\n }\n }\n }\n }\n\n /**\n * Internal helper to yield an event with metadata.\n */\n private async *emit(\n event: TEvent,\n context?: RuntimeContext<TState, TEvent>,\n ): AsyncGenerator<TEvent> {\n this.queue.push(event);\n\n if (this.isEmitting) return;\n\n this.isEmitting = true;\n try {\n while (this.queue.length > 0) {\n const current = this.queue.shift()!;\n yield current;\n }\n } finally {\n this.isEmitting = false;\n }\n }\n}\n","import { Runtime } from \"./runtime\";\n\nexport const MelonyRuntime = Runtime;","import { Event } from \"../types\";\n\n/**\n * Convert an async generator of events to an HTTP streaming response\n * Exported for backward compatibility and standalone usage\n */\nexport function createStreamResponse(\n generator: AsyncGenerator<Event>,\n): Response {\n const encoder = new TextEncoder();\n const stream = new ReadableStream({\n async start(controller) {\n try {\n for await (const message of generator) {\n // Format as SSE: data: {...}\\n\\n\n const chunk = `data: ${JSON.stringify(message)}\\n\\n`;\n controller.enqueue(encoder.encode(chunk));\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n },\n });\n}\n","import {\n Event,\n EventHandler,\n Config,\n RuntimeContext,\n} from \"./types\";\nimport { Runtime } from \"./runtime\";\nimport { createStreamResponse } from \"./utils/create-stream-response\";\n\n/**\n * A Melony plugin is a function that receives the builder and extends it.\n * This allows for modularizing common handlers.\n */\nexport type MelonyPlugin<TState = any, TEvent extends Event = Event> = (\n builder: MelonyBuilder<TState, TEvent>\n) => void;\n\n/**\n * Fluent builder for creating Melony agents with excellent developer experience.\n * Provides method chaining for handlers and plugins with full TypeScript support.\n */\nexport class MelonyBuilder<\n TState = any,\n TEvent extends Event = Event\n> {\n private config: Config<TState, TEvent>;\n\n constructor(initialConfig?: Partial<Config<TState, TEvent>>) {\n this.config = {\n eventHandlers: initialConfig?.eventHandlers ?? new Map(),\n };\n }\n\n /**\n * Add an event handler for a specific event type. Supports method chaining.\n * The handler receives the narrowed event type based on the eventType string.\n */\n on<K extends TEvent[\"type\"]>(\n eventType: K,\n handler: (\n event: Extract<TEvent, { type: K }>,\n context: RuntimeContext<TState, TEvent>\n ) => AsyncGenerator<TEvent, void, unknown> | void\n ): this {\n if (!this.config.eventHandlers.has(eventType)) {\n this.config.eventHandlers.set(eventType, []);\n }\n // Cast is safe because runtime only calls this handler for matching event types\n this.config.eventHandlers.get(eventType)!.push(handler as EventHandler<TState, TEvent>);\n return this;\n }\n\n /**\n * Use a plugin to extend the builder.\n * This is ideal for modularizing common handlers.\n */\n use(plugin: MelonyPlugin<TState, TEvent>): this {\n plugin(this);\n return this;\n }\n\n /**\n * Build and return the Melony runtime instance.\n * This is the final method in the fluent chain.\n */\n build(): Runtime<TState, TEvent> {\n return new Runtime(this.config);\n }\n\n /**\n * Execute and stream the response for an event.\n * This is a convenience method that builds the runtime and calls run().\n */\n async streamResponse(\n event: TEvent,\n options?: { state?: TState; runId?: string }\n ): Promise<Response> {\n const runtime = this.build();\n const generator = runtime.run(event, options);\n return createStreamResponse(generator);\n }\n\n /**\n * Get the current configuration (useful for debugging or serialization).\n */\n getConfig(): Config<TState, TEvent> {\n return { ...this.config };\n }\n}\n\n/**\n * Factory function to create a new Melony builder instance.\n * This is the entry point for the fluent API.\n */\nexport function melony<\n TState = any,\n TEvent extends Event = Event\n>(initialConfig?: Partial<Config<TState, TEvent>>): MelonyBuilder<TState, TEvent> {\n return new MelonyBuilder<TState, TEvent>(initialConfig);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melony",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1,118 +0,0 @@
1
- /**
2
- * The Melony Runtime.
3
- * Fully unopinionated - executes a single action per run.
4
- * Chaining/looping is left to userland.
5
- */
6
- declare class Runtime<TState = any, TEvent extends Event = Event> {
7
- readonly config: Config<TState, TEvent>;
8
- private queue;
9
- private isEmitting;
10
- constructor(config: Config<TState, TEvent>);
11
- /**
12
- * Run an action by name with given params.
13
- * This is the primary way to execute actions.
14
- */
15
- execute(actionName: string, params: any, options?: {
16
- state?: TState;
17
- runId?: string;
18
- }): AsyncGenerator<TEvent>;
19
- /**
20
- * Process an incoming event through the runtime.
21
- * All event processing is handled by user-defined event handlers.
22
- */
23
- run(event: TEvent): AsyncGenerator<TEvent>;
24
- /**
25
- * Run all event handlers that match the given event type.
26
- */
27
- private runEventHandlers;
28
- /**
29
- * Internal helper to yield an event with metadata.
30
- * Handlers are invoked by runEventHandlers when events bubble up.
31
- */
32
- private emit;
33
- }
34
-
35
- type Role = "user" | "assistant" | "system";
36
- /**
37
- * System-managed metadata for an event.
38
- */
39
- interface EventMeta<TState = any> {
40
- id: string;
41
- runId: string;
42
- timestamp: number;
43
- role: Role;
44
- state: TState;
45
- [key: string]: any;
46
- }
47
- /**
48
- * The core Event structure.
49
- * Fully unopinionated - just type, data, and optional metadata.
50
- */
51
- type Event<TData = any> = {
52
- type: string;
53
- data: TData;
54
- meta?: EventMeta;
55
- };
56
- /**
57
- * Built-in action lifecycle events emitted by the runtime.
58
- */
59
- interface ActionBeforeEvent extends Event<{
60
- action: string;
61
- params: any;
62
- }> {
63
- type: "action:before";
64
- }
65
- interface ActionAfterEvent extends Event<{
66
- action: string;
67
- result: any;
68
- }> {
69
- type: "action:after";
70
- }
71
- /**
72
- * Built-in call-action event for triggering action execution.
73
- */
74
- interface CallActionEvent extends Event<{
75
- action: string;
76
- params: unknown;
77
- }> {
78
- type: "call-action";
79
- }
80
- /**
81
- * Built-in error event emitted by the runtime.
82
- */
83
- interface ErrorEvent extends Event<{
84
- message: string;
85
- action?: string;
86
- stack?: string;
87
- }> {
88
- type: "error";
89
- }
90
- type ActionExecute<TParams = any, TState = any, TEvent extends Event = Event> = (params: TParams, context: RuntimeContext<TState, TEvent>) => AsyncGenerator<TEvent, any, unknown>;
91
- interface Action<TParams = any, TState = any, TEvent extends Event = Event> {
92
- name: string;
93
- execute: ActionExecute<TParams, TState, TEvent>;
94
- }
95
- interface RuntimeContext<TState = any, TEvent extends Event = Event> {
96
- state: TState;
97
- runId: string;
98
- actions: Record<string, Action<any, TState, TEvent>>;
99
- runtime: Runtime<TState, TEvent>;
100
- /**
101
- * Immediately interrupts the runtime execution.
102
- * If an event is provided, it will be emitted before the runtime stops.
103
- */
104
- suspend: (event?: TEvent) => never;
105
- }
106
- /**
107
- * Event handler function for processing events.
108
- * Can return events to emit or undefined to continue processing.
109
- */
110
- type EventHandler<TState = any, TEvent extends Event = Event> = (event: TEvent, context: RuntimeContext<TState, TEvent>) => AsyncGenerator<TEvent, void, unknown> | void;
111
- interface Config<TState = any, TEvent extends Event = Event> {
112
- actions: Record<string, Action<any, TState, TEvent>>;
113
- eventHandlers: Map<string, EventHandler<TState, TEvent>[]>;
114
- }
115
-
116
- declare const generateId: () => string;
117
-
118
- export { type ActionExecute as A, type Config as C, type Event as E, Runtime as R, type Action as a, type RuntimeContext as b, type Role as c, type EventMeta as d, type ActionBeforeEvent as e, type ActionAfterEvent as f, type CallActionEvent as g, type ErrorEvent as h, type EventHandler as i, generateId as j };