melony 0.1.50 → 0.1.53

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.
@@ -1,6 +1,6 @@
1
1
  import { generateId } from './chunk-WAI5H335.js';
2
2
 
3
- // src/types.ts
3
+ // src/ui.ts
4
4
  var ui = {
5
5
  card: (props) => {
6
6
  const { children, ...rest } = props;
@@ -30,17 +30,17 @@ var ui = {
30
30
  type: "text",
31
31
  props: { ...props, value }
32
32
  }),
33
- heading: (value, level = 1) => ({
33
+ heading: (value, level = 1, props) => ({
34
34
  type: "heading",
35
- props: { value, level }
35
+ props: { ...props, value, level }
36
36
  }),
37
37
  badge: (label, variant = "primary", size = "md") => ({
38
38
  type: "badge",
39
39
  props: { label, variant, size }
40
40
  }),
41
- image: (src, alt, size = "md", groupId) => ({
41
+ image: (src, props) => ({
42
42
  type: "image",
43
- props: { src, alt, size, groupId }
43
+ props: { ...props, src }
44
44
  }),
45
45
  video: (src, props) => ({
46
46
  type: "video",
@@ -54,10 +54,10 @@ var ui = {
54
54
  type: "chart",
55
55
  props
56
56
  }),
57
- list: (children) => ({
58
- type: "list",
59
- children
60
- }),
57
+ list: (props) => {
58
+ const { children, ...rest } = props;
59
+ return { type: "list", props: rest, children };
60
+ },
61
61
  listItem: (props) => {
62
62
  const { children, ...rest } = props;
63
63
  return { type: "listItem", props: rest, children };
@@ -106,6 +106,14 @@ var ui = {
106
106
  type: "button",
107
107
  props
108
108
  }),
109
+ float: (props) => {
110
+ const { children, ...rest } = props;
111
+ return { type: "float", props: rest, children };
112
+ },
113
+ dropdown: (props) => {
114
+ const { children, ...rest } = props;
115
+ return { type: "dropdown", props: rest, children };
116
+ },
109
117
  actions: {
110
118
  navigate: (url) => ({
111
119
  type: "client:navigate",
@@ -376,5 +384,5 @@ var action = (config) => config;
376
384
  var plugin = (config) => config;
377
385
 
378
386
  export { Runtime, action, melony, plugin, ui };
379
- //# sourceMappingURL=chunk-IK3OHUHO.js.map
380
- //# sourceMappingURL=chunk-IK3OHUHO.js.map
387
+ //# sourceMappingURL=chunk-W35Y2YZP.js.map
388
+ //# sourceMappingURL=chunk-W35Y2YZP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui.ts","../src/runtime.ts"],"names":["event","plugin","action"],"mappings":"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","file":"chunk-W35Y2YZP.js","sourcesContent":["import { UIColor, UIContract, UINode, UISize, Event, UISpacing, UIWidth, UIRadius } from \"./types\";\n\n/**\n * UI Builder for SDUI.\n * Typed using the UIContract source of truth.\n */\nexport const ui = {\n card: (\n props: UIContract[\"card\"] & { children?: UINode<any>[] }\n ): UINode<\"card\"> => {\n const { children, ...rest } = props;\n return { type: \"card\", props: rest, children };\n },\n row: (\n props: UIContract[\"row\"] & { children?: UINode<any>[] }\n ): UINode<\"row\"> => {\n const { children, ...rest } = props;\n return { type: \"row\", props: rest, children };\n },\n col: (\n props: UIContract[\"col\"] & { children?: UINode<any>[] }\n ): UINode<\"col\"> => {\n const { children, ...rest } = props;\n return { type: \"col\", props: rest, children };\n },\n box: (\n props: UIContract[\"box\"] & { children?: UINode<any>[] }\n ): UINode<\"box\"> => {\n const { children, ...rest } = props;\n return { type: \"box\", props: rest, children };\n },\n spacer: (props: UIContract[\"spacer\"]): UINode<\"spacer\"> => ({\n type: \"spacer\",\n props,\n }),\n divider: (props: UIContract[\"divider\"]): UINode<\"divider\"> => ({\n type: \"divider\",\n props,\n }),\n text: (\n value: string,\n props?: Omit<UIContract[\"text\"], \"value\">\n ): UINode<\"text\"> => ({\n type: \"text\",\n props: { ...props, value },\n }),\n heading: (\n value: string,\n level: UIContract[\"heading\"][\"level\"] = 1,\n props?: Omit<UIContract[\"heading\"], \"value\" | \"level\">\n ): UINode<\"heading\"> => ({\n type: \"heading\",\n props: { ...props, value, level },\n }),\n badge: (\n label: string,\n variant: UIContract[\"badge\"][\"variant\"] = \"primary\",\n size: UISize = \"md\"\n ): UINode<\"badge\"> => ({\n type: \"badge\",\n props: { label, variant, size },\n }),\n image: (\n src: string,\n props?: Omit<UIContract[\"image\"], \"src\">\n ): UINode<\"image\"> => ({\n type: \"image\",\n props: { ...props, src },\n }),\n video: (\n src: string,\n props?: Omit<UIContract[\"video\"], \"src\">\n ): UINode<\"video\"> => ({\n type: \"video\",\n props: { ...props, src },\n }),\n icon: (\n name: string,\n size: UISize | number = \"md\",\n color?: UIColor\n ): UINode<\"icon\"> => ({\n type: \"icon\",\n props: { name, size, color },\n }),\n chart: (props: UIContract[\"chart\"]): UINode<\"chart\"> => ({\n type: \"chart\",\n props,\n }),\n list: (props: UIContract[\"list\"] & { children: UINode<any>[] }): UINode<\"list\"> => {\n const { children, ...rest } = props;\n return { type: \"list\", props: rest, children };\n },\n listItem: (\n props: UIContract[\"listItem\"] & { children: UINode<any>[] }\n ): UINode<\"listItem\"> => {\n const { children, ...rest } = props;\n return { type: \"listItem\", props: rest, children };\n },\n form: (\n props: UIContract[\"form\"] & { children?: UINode<any>[] }\n ): UINode<\"form\"> => {\n const { children, ...rest } = props;\n return { type: \"form\", props: rest, children };\n },\n input: (props: UIContract[\"input\"]): UINode<\"input\"> => ({\n type: \"input\",\n props,\n }),\n textarea: (props: UIContract[\"textarea\"]): UINode<\"textarea\"> => ({\n type: \"textarea\",\n props,\n }),\n select: (props: UIContract[\"select\"]): UINode<\"select\"> => ({\n type: \"select\",\n props,\n }),\n checkbox: (props: UIContract[\"checkbox\"]): UINode<\"checkbox\"> => ({\n type: \"checkbox\",\n props,\n }),\n hidden: (props: UIContract[\"hidden\"]): UINode<\"hidden\"> => ({\n type: \"hidden\",\n props,\n }),\n radioGroup: (props: UIContract[\"radioGroup\"]): UINode<\"radioGroup\"> => ({\n type: \"radioGroup\",\n props,\n }),\n label: (\n value: string,\n props?: Omit<UIContract[\"label\"], \"value\">\n ): UINode<\"label\"> => ({\n type: \"label\",\n props: { ...props, value },\n }),\n colorPicker: (props: UIContract[\"colorPicker\"]): UINode<\"colorPicker\"> => ({\n type: \"colorPicker\",\n props,\n }),\n upload: (props: UIContract[\"upload\"]): UINode<\"upload\"> => ({\n type: \"upload\",\n props,\n }),\n button: (props: UIContract[\"button\"]): UINode<\"button\"> => ({\n type: \"button\",\n props,\n }),\n float: (\n props: UIContract[\"float\"] & { children?: UINode<any>[] }\n ): UINode<\"float\"> => {\n const { children, ...rest } = props;\n return { type: \"float\", props: rest, children };\n },\n dropdown: (\n props: UIContract[\"dropdown\"] & { children?: UINode<any>[] }\n ): UINode<\"dropdown\"> => {\n const { children, ...rest } = props;\n return { type: \"dropdown\", props: rest, children };\n },\n actions: {\n navigate: (url: string): Event => ({\n type: \"client:navigate\",\n data: { url },\n }),\n openUrl: (url: string, target = \"_blank\"): Event => ({\n type: \"client:open-url\",\n data: { url, target },\n }),\n copy: (text: string): Event => ({ type: \"client:copy\", data: { text } }),\n reset: (): Event => ({ type: \"client:reset\" }),\n invalidateQuery: (queryKey: any[]): Event => ({\n type: \"client:invalidate-query\",\n data: { queryKey },\n }),\n },\n};\n","import {\n Action,\n Event,\n NextAction,\n RuntimeContext,\n Config,\n Plugin,\n HookGenerator,\n} from \"./types\";\nimport { ui } from \"./ui\";\nimport { generateId } from \"./utils/generate-id\";\nimport { z } from \"zod\";\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 Slim Runtime.\n * Single Responsibility: Orchestrate Event -> Action -> Event transitions.\n */\nexport class Runtime<TState = any> {\n private config: Config<TState>;\n\n constructor(config: Config<TState>) {\n this.config = config;\n }\n\n public async *run(event: Event): AsyncGenerator<Event> {\n const runId = event.runId ?? generateId();\n\n const context: RuntimeContext<TState> = {\n state: (event.state ?? {}) as TState,\n runId,\n stepCount: 0,\n actions: this.config.actions,\n ui,\n suspend: (event?: Event) => {\n throw event || { type: \"run-suspended\" };\n },\n };\n\n try {\n let nextAction: NextAction | void = undefined;\n\n // 1. Trigger Plugins: onBeforeRun\n for (const plugin of this.config.plugins || []) {\n if (plugin.onBeforeRun) {\n const result = yield* this.callHook(\n plugin.onBeforeRun({ event }, context),\n context\n );\n if (result) {\n nextAction = result as NextAction;\n }\n }\n }\n\n // 2. Trigger Hook: onBeforeRun\n if (this.config.hooks?.onBeforeRun) {\n const result = yield* this.callHook(\n this.config.hooks.onBeforeRun({ event }, context),\n context\n );\n if (result) {\n nextAction = result as NextAction;\n }\n }\n\n // Initial dispatch of the incoming event to the agent's brain\n // Priority:\n // 1. nextAction already set by onBeforeRun hooks\n // 2. nextAction provided in the event itself\n // 3. Dispatch to brain to decide nextAction\n if (!nextAction && event.nextAction) {\n nextAction = event.nextAction;\n }\n\n if (!nextAction && this.config.brain) {\n nextAction = yield* this.dispatchToBrain(event, context);\n }\n\n // Agentic loop\n while (nextAction) {\n if (context.stepCount++ >= (this.config.safetyMaxSteps ?? 10)) {\n yield* this.emit(\n { type: \"error\", data: { message: \"Max steps exceeded\" } },\n context\n );\n break;\n }\n\n const current: NextAction = nextAction;\n nextAction = undefined; // Reset\n\n // 1. Resolve Action\n const actionName: string | undefined = current.action;\n\n if (!actionName) {\n yield* this.emit(\n {\n type: \"error\",\n data: { message: \"No action name provided in NextAction\" },\n },\n context\n );\n break;\n }\n\n const action: Action<any, TState> = this.config.actions[actionName];\n\n if (!action) {\n yield* this.emit(\n {\n type: \"error\",\n data: { message: `Action ${actionName} not found` },\n },\n context\n );\n break;\n }\n\n // 2. Execute Action\n const result = yield* this.executeAction(action, current, context);\n\n // 3. Decide Next Step\n if (this.config.brain) {\n // If we have a brain, feed the result back to it to decide what to do next.\n // This keeps the brain in the loop for multi-step reasoning.\n nextAction = yield* this.dispatchToBrain(\n {\n type: \"action-result\",\n data: {\n ...current, // Preserve all metadata (like toolCallId)\n action: actionName,\n result,\n },\n },\n context\n );\n } else {\n // Simple mode: follow the action's own suggestion for the next step.\n nextAction = result;\n }\n }\n\n // 1. Trigger Plugins: onAfterRun\n for (const plugin of this.config.plugins || []) {\n if (plugin.onAfterRun) {\n yield* this.callHook(plugin.onAfterRun(context), context);\n }\n }\n\n // 2. Trigger Hook: onAfterRun\n if (this.config.hooks?.onAfterRun) {\n yield* this.callHook(this.config.hooks.onAfterRun(context), context);\n }\n } catch (error) {\n let eventToEmit: Event | undefined;\n\n if (isEvent(error)) {\n eventToEmit = error;\n } else {\n // Wrap unexpected errors into an Event\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 };\n }\n\n if (eventToEmit) {\n yield* this.emit(eventToEmit, context);\n }\n\n return; // Gracefully stop the runtime\n }\n }\n\n private async *dispatchToBrain(\n event: Event,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, NextAction | void> {\n const generator = this.config.brain!(event, context);\n while (true) {\n const { value, done } = await generator.next();\n if (done) return value as NextAction | void;\n yield* this.emit(value as Event, context);\n }\n }\n\n private async *executeAction(\n action: Action<any, TState>,\n nextAction: NextAction,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, NextAction | void> {\n const params = nextAction.params;\n\n // 1. Trigger Plugins: onBeforeAction\n for (const plugin of this.config.plugins || []) {\n if (plugin.onBeforeAction) {\n const hookResult = yield* this.callHook(\n plugin.onBeforeAction({ action, params, nextAction }, context),\n context\n );\n if (hookResult) {\n nextAction = hookResult as NextAction;\n }\n }\n }\n\n // 2. Trigger Hook: onBeforeAction\n if (this.config.hooks?.onBeforeAction) {\n const hookResult = yield* this.callHook(\n this.config.hooks.onBeforeAction(\n { action, params, nextAction },\n context\n ),\n context\n );\n if (hookResult) {\n nextAction = hookResult as NextAction;\n }\n }\n\n try {\n const generator = action.execute(params, context);\n let result: NextAction | void;\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) {\n result = value as NextAction | void;\n break;\n }\n yield* this.emit(value as Event, context);\n }\n\n // 3. Trigger Plugins: onAfterAction\n for (const plugin of this.config.plugins || []) {\n if (plugin.onAfterAction) {\n const extra = yield* this.callHook(\n plugin.onAfterAction({ action, data: result }, context),\n context\n );\n if (extra) {\n nextAction = extra as NextAction;\n }\n }\n }\n\n // 4. Trigger Hook: onAfterAction\n if (this.config.hooks?.onAfterAction) {\n const extra = yield* this.callHook(\n this.config.hooks.onAfterAction({ action, data: result }, context),\n context\n );\n if (extra) {\n nextAction = extra as NextAction;\n }\n }\n\n return result;\n } catch (error) {\n if (isEvent(error)) throw error;\n\n throw {\n type: \"error\",\n data: {\n action: action.name,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n };\n }\n }\n\n /**\n * Internal helper to call a hook (generator) and yield its events.\n */\n private async *callHook<T>(\n generator: HookGenerator<T> | undefined,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, T | void> {\n if (!generator) return;\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) return value as T | void;\n yield* this.emit(value as Event, context);\n }\n }\n\n /**\n * Internal helper to yield an event and trigger the onEvent hook.\n */\n private async *emit(\n event: Event,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event> {\n const finalEvent = {\n ...event,\n runId: context.runId,\n timestamp: event.timestamp ?? Date.now(),\n role: event.role ?? \"assistant\",\n state: context.state,\n };\n\n // Yield the actual event first\n yield finalEvent;\n\n // 1. Trigger Plugins: onEvent\n for (const plugin of this.config.plugins || []) {\n if (plugin.onEvent) {\n const generator = plugin.onEvent(finalEvent, context);\n for await (const extra of generator) {\n yield { ...extra, runId: context.runId, timestamp: Date.now() };\n }\n }\n }\n\n // 2. Trigger Hook: onEvent for side-effects or extra events\n if (this.config.hooks?.onEvent) {\n const generator = this.config.hooks.onEvent(finalEvent, context);\n for await (const extra of generator) {\n // Yield extra event from hook, ensuring it has required metadata\n yield { ...extra, runId: context.runId, timestamp: Date.now() };\n }\n }\n }\n}\n\nexport const melony = <TState = any>(config: Config<TState>) => {\n const runtime = new Runtime<TState>(config);\n return {\n config,\n run: runtime.run.bind(runtime),\n };\n};\n\n/**\n * Helper to define an action with full type inference.\n */\nexport const action = <T extends z.ZodSchema, TState = any>(\n config: Action<T, TState>\n): Action<T, TState> => config;\n\n/**\n * Helper to define a plugin.\n */\nexport const plugin = <TState = any>(config: Plugin<TState>): Plugin<TState> =>\n config;\n"]}
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { E as Event, C as Config } from './types-Cn56J4A7.js';
1
+ import { E as Event, C as Config } from './types-BWIe3XvZ.js';
2
2
  export { g as generateId } from './generate-id-DU8kwYc2.js';
3
3
  import 'zod';
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Config, E as Event, A as Action, P as Plugin, M as Message } from './types-Cn56J4A7.js';
2
- export { i as ActionExecute, B as Brain, H as HookGenerator, k as Hooks, N as NextAction, R as Role, j as RuntimeContext, a as UIAlign, e as UIColor, g as UIContract, b as UIJustify, h as UINode, d as UIOrientation, U as UISize, f as UISpacing, c as UIWrap, u as ui } from './types-Cn56J4A7.js';
1
+ import { C as Config, E as Event, A as Action, P as Plugin, M as Message } from './types-BWIe3XvZ.js';
2
+ export { l as ActionExecute, B as Brain, H as HookGenerator, n as Hooks, N as NextAction, R as Role, m as RuntimeContext, a as UIAlign, e as UIColor, j as UIContract, b as UIJustify, k as UINode, d as UIOrientation, i as UIRadius, h as UIShadow, U as UISize, f as UISpacing, g as UIWidth, c as UIWrap, u as ui } from './types-BWIe3XvZ.js';
3
3
  import { z } from 'zod';
4
4
  export { g as generateId } from './generate-id-DU8kwYc2.js';
5
5
 
@@ -43,4 +43,11 @@ declare function createStreamResponse(generator: AsyncGenerator<Event>): Respons
43
43
 
44
44
  declare function convertEventsToMessages(events: Event[]): Message[];
45
45
 
46
- export { Action, Config, Event, Message, Plugin, Runtime, action, convertEventsToMessages, createStreamResponse, melony, plugin };
46
+ /**
47
+ * Filters a list of events by their slot property.
48
+ * If multiple events have the same slot, only the latest one is kept,
49
+ * but its position in the returned array corresponds to the first time that slot appeared.
50
+ */
51
+ declare function filterEventsBySlots(events: Event[]): Event[];
52
+
53
+ export { Action, Config, Event, Message, Plugin, Runtime, action, convertEventsToMessages, createStreamResponse, filterEventsBySlots, melony, plugin };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { createStreamResponse } from './chunk-CFG7FFEZ.js';
2
- export { Runtime, action, melony, plugin, ui } from './chunk-IK3OHUHO.js';
2
+ export { Runtime, action, melony, plugin, ui } from './chunk-W35Y2YZP.js';
3
3
  export { generateId } from './chunk-WAI5H335.js';
4
4
 
5
5
  // src/utils/convert-events-to-messages.ts
@@ -27,6 +27,32 @@ function convertEventsToMessages(events) {
27
27
  return messages;
28
28
  }
29
29
 
30
- export { convertEventsToMessages };
30
+ // src/utils/filter-events-by-slots.ts
31
+ function filterEventsBySlots(events) {
32
+ const firstSlotIndexes = /* @__PURE__ */ new Map();
33
+ const latestSlotIndexes = /* @__PURE__ */ new Map();
34
+ events.forEach((event, index) => {
35
+ if (event.slot) {
36
+ if (!firstSlotIndexes.has(event.slot)) {
37
+ firstSlotIndexes.set(event.slot, index);
38
+ }
39
+ latestSlotIndexes.set(event.slot, index);
40
+ }
41
+ });
42
+ const result = [];
43
+ events.forEach((event, index) => {
44
+ if (event.slot) {
45
+ if (firstSlotIndexes.get(event.slot) === index) {
46
+ const latestIndex = latestSlotIndexes.get(event.slot);
47
+ result.push(events[latestIndex]);
48
+ }
49
+ } else {
50
+ result.push(event);
51
+ }
52
+ });
53
+ return result;
54
+ }
55
+
56
+ export { convertEventsToMessages, filterEventsBySlots };
31
57
  //# sourceMappingURL=index.js.map
32
58
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/convert-events-to-messages.ts"],"names":[],"mappings":";;;;;AAEO,SAAS,wBAAwB,MAAA,EAA4B;AAClE,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAEjC,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI,cAAA,GAAiC,IAAA;AAErC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,WAAA;AAC3B,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAMpB,IAAA,IACE,CAAC,cAAA,IACD,cAAA,CAAe,IAAA,KAAS,IAAA,IACvB,SAAS,cAAA,CAAe,KAAA,IAAS,KAAA,KAAU,cAAA,CAAe,KAAA,EAC3D;AACA,MAAA,cAAA,GAAiB;AAAA,QACf,IAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAK,CAAA;AAAA,QACf;AAAA,OACF;AACA,MAAA,QAAA,CAAS,KAAK,cAAc,CAAA;AAAA,IAC9B,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,OAAA,CAAQ,KAAK,KAAK,CAAA;AAEjC,MAAA,IAAI,CAAC,cAAA,CAAe,KAAA,IAAS,KAAA,EAAO;AAClC,QAAA,cAAA,CAAe,KAAA,GAAQ,KAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT","file":"index.js","sourcesContent":["import { Event, Message } from \"../types\";\n\nexport function convertEventsToMessages(events: Event[]): Message[] {\n if (events.length === 0) return [];\n\n const messages: Message[] = [];\n let currentMessage: Message | null = null;\n\n for (const event of events) {\n const role = event.role || \"assistant\";\n const runId = event.runId;\n\n // Start a new message if:\n // 1. No current message\n // 2. Role changed\n // 3. runId changed (and both have runIds)\n if (\n !currentMessage ||\n currentMessage.role !== role ||\n (runId && currentMessage.runId && runId !== currentMessage.runId)\n ) {\n currentMessage = {\n role: role,\n content: [event],\n runId,\n };\n messages.push(currentMessage);\n } else {\n currentMessage.content.push(event);\n // If the current message didn't have a runId but this event does, update it\n if (!currentMessage.runId && runId) {\n currentMessage.runId = runId;\n }\n }\n }\n\n return messages;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/convert-events-to-messages.ts","../src/utils/filter-events-by-slots.ts"],"names":[],"mappings":";;;;;AAEO,SAAS,wBAAwB,MAAA,EAA4B;AAClE,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAEjC,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI,cAAA,GAAiC,IAAA;AAErC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,WAAA;AAC3B,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAMpB,IAAA,IACE,CAAC,cAAA,IACD,cAAA,CAAe,IAAA,KAAS,IAAA,IACvB,SAAS,cAAA,CAAe,KAAA,IAAS,KAAA,KAAU,cAAA,CAAe,KAAA,EAC3D;AACA,MAAA,cAAA,GAAiB;AAAA,QACf,IAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAK,CAAA;AAAA,QACf;AAAA,OACF;AACA,MAAA,QAAA,CAAS,KAAK,cAAc,CAAA;AAAA,IAC9B,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,OAAA,CAAQ,KAAK,KAAK,CAAA;AAEjC,MAAA,IAAI,CAAC,cAAA,CAAe,KAAA,IAAS,KAAA,EAAO;AAClC,QAAA,cAAA,CAAe,KAAA,GAAQ,KAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;;;AC9BO,SAAS,oBAAoB,MAAA,EAA0B;AAC5D,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAoB;AACjD,EAAA,MAAM,iBAAA,uBAAwB,GAAA,EAAoB;AAElD,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,KAAA,KAAU;AAC/B,IAAA,IAAI,MAAM,IAAA,EAAM;AACd,MAAA,IAAI,CAAC,gBAAA,CAAiB,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AACrC,QAAA,gBAAA,CAAiB,GAAA,CAAI,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AAAA,MACxC;AACA,MAAA,iBAAA,CAAkB,GAAA,CAAI,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AAAA,IACzC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,SAAkB,EAAC;AAEzB,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,KAAA,KAAU;AAC/B,IAAA,IAAI,MAAM,IAAA,EAAM;AACd,MAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,KAAA,CAAM,IAAI,MAAM,KAAA,EAAO;AAC9C,QAAA,MAAM,WAAA,GAAc,iBAAA,CAAkB,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACpD,QAAA,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,MACjC;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT","file":"index.js","sourcesContent":["import { Event, Message } from \"../types\";\n\nexport function convertEventsToMessages(events: Event[]): Message[] {\n if (events.length === 0) return [];\n\n const messages: Message[] = [];\n let currentMessage: Message | null = null;\n\n for (const event of events) {\n const role = event.role || \"assistant\";\n const runId = event.runId;\n\n // Start a new message if:\n // 1. No current message\n // 2. Role changed\n // 3. runId changed (and both have runIds)\n if (\n !currentMessage ||\n currentMessage.role !== role ||\n (runId && currentMessage.runId && runId !== currentMessage.runId)\n ) {\n currentMessage = {\n role: role,\n content: [event],\n runId,\n };\n messages.push(currentMessage);\n } else {\n currentMessage.content.push(event);\n // If the current message didn't have a runId but this event does, update it\n if (!currentMessage.runId && runId) {\n currentMessage.runId = runId;\n }\n }\n }\n\n return messages;\n}\n","import { Event } from \"../types\";\n\n/**\n * Filters a list of events by their slot property.\n * If multiple events have the same slot, only the latest one is kept,\n * but its position in the returned array corresponds to the first time that slot appeared.\n */\nexport function filterEventsBySlots(events: Event[]): Event[] {\n const firstSlotIndexes = new Map<string, number>();\n const latestSlotIndexes = new Map<string, number>();\n\n events.forEach((event, index) => {\n if (event.slot) {\n if (!firstSlotIndexes.has(event.slot)) {\n firstSlotIndexes.set(event.slot, index);\n }\n latestSlotIndexes.set(event.slot, index);\n }\n });\n\n const result: Event[] = [];\n\n events.forEach((event, index) => {\n if (event.slot) {\n if (firstSlotIndexes.get(event.slot) === index) {\n const latestIndex = latestSlotIndexes.get(event.slot)!;\n result.push(events[latestIndex]);\n }\n } else {\n result.push(event);\n }\n });\n\n return result;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { A as Action, j as RuntimeContext, P as Plugin } from '../types-Cn56J4A7.js';
1
+ import { A as Action, m as RuntimeContext, P as Plugin } from '../types-BWIe3XvZ.js';
2
2
  import 'zod';
3
3
 
4
4
  interface RequireApprovalOptions {
@@ -1,4 +1,4 @@
1
- import { plugin, ui } from '../chunk-IK3OHUHO.js';
1
+ import { plugin, ui } from '../chunk-W35Y2YZP.js';
2
2
  import '../chunk-WAI5H335.js';
3
3
 
4
4
  // src/plugins/require-approval.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/require-approval.ts"],"names":[],"mappings":"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","file":"require-approval.js","sourcesContent":["import { plugin } from \"../runtime\";\nimport { ui } from \"../types\";\nimport type { Action, RuntimeContext } from \"../types\";\n\nexport interface RequireApprovalOptions {\n /**\n * List of action names that require explicit approval.\n * If not provided, all actions will require approval.\n */\n actions?: string[];\n\n /**\n * Optional secret to sign the approval payload.\n * If provided, the plugin will verify that the parameters haven't been\n * tampered with between the request and the approval.\n */\n secret?: string;\n\n /**\n * Custom message to show in the approval card.\n */\n message?: string | ((action: string, params: any) => string);\n\n /**\n * Optional condition to check if approval is needed dynamically.\n */\n shouldApprove?: (\n action: Action<any>,\n params: any,\n context: RuntimeContext\n ) => boolean | Promise<boolean>;\n}\n\n/**\n * A plugin that intercepts actions and requires human approval before execution.\n * It uses SDUI to prompt the user and handles the resumption of the agentic loop.\n */\nexport const requireApproval = (options: RequireApprovalOptions = {}) => {\n return plugin({\n name: \"require-approval\",\n\n /**\n * Step 1: Handle the resumption when the user clicks \"Approve\" or \"Cancel\".\n * We verify the one-time-use approvalId to prevent replay attacks or double-clicks.\n */\n onBeforeRun: async function* ({ event }, context) {\n if (\n event.type === \"action-approved\" ||\n event.type === \"action-rejected\"\n ) {\n const { token, approvalId } = event.data || {};\n const action = event.nextAction?.action;\n const params = event.nextAction?.params;\n\n // 1. Check if this specific request exists and hasn't been used\n const pending = context.state.__pending_approvals?.[approvalId];\n if (!pending) {\n context.suspend({\n role: \"assistant\",\n type: \"error\",\n data: {\n message:\n \"Security Error: This approval request is invalid or has already been used.\",\n },\n ui: ui.card({\n title: \"Security Error\",\n children: [\n ui.text(\n \"This approval request is invalid or has already been used.\"\n ),\n ],\n }),\n });\n }\n\n // 2. Consume the token immediately (Destroy after usage)\n delete context.state.__pending_approvals[approvalId];\n\n if (event.type === \"action-approved\") {\n // 3. Security: Verify the token if a secret was provided\n if (options.secret) {\n const expectedToken = await signPayload(\n { action, params, approvalId },\n options.secret\n );\n if (token !== expectedToken) {\n yield {\n type: \"error\",\n data: {\n message:\n \"Security Warning: Approval token mismatch. Execution blocked.\",\n },\n };\n return;\n }\n }\n\n // 4. Store approval in ephemeral state for the upcoming action execution\n context.state.__approved_action = { action, params };\n\n // No need to return anything here!\n // The Runtime will automatically pick up `event.nextAction`\n // which was attached to the \"action-approved\" event.\n return;\n }\n\n // Handle Rejection\n context.suspend({\n type: \"error\",\n data: {\n message: `Action '${action}' was rejected by the user.`,\n },\n });\n }\n },\n\n /**\n * Step 2: Intercept actions that require approval.\n */\n onBeforeAction: async function* ({ action, params, nextAction }, context) {\n // 1. Check if this action needs approval\n const isTargetAction =\n !options.actions || options.actions.includes(action.name);\n if (!isTargetAction) return;\n\n if (options.shouldApprove) {\n const needsApproval = await options.shouldApprove(\n action,\n params,\n context\n );\n if (!needsApproval) return;\n }\n\n // 2. Check if it was ALREADY approved in this run\n const approval = context.state.__approved_action;\n if (\n approval &&\n approval.action === action.name &&\n JSON.stringify(approval.params) === JSON.stringify(params)\n ) {\n delete context.state.__approved_action;\n return; // Proceed to execution\n }\n\n // 3. Suspend and request approval with a one-time-use nonce\n const approvalId = Math.random().toString(36).substring(2, 15);\n context.state.__pending_approvals =\n context.state.__pending_approvals || {};\n context.state.__pending_approvals[approvalId] = true;\n\n const token = options.secret\n ? await signPayload(\n { action: action.name, params, approvalId },\n options.secret\n )\n : undefined;\n\n const message =\n typeof options.message === \"function\"\n ? options.message(action.name, params)\n : options.message ||\n `The agent wants to execute **${action.name}**. Do you approve?`;\n\n context.suspend({\n type: \"hitl-required\",\n nextAction,\n data: { token, approvalId },\n slot: \"approval\",\n ui: ui.card({\n title: \"Approval Required\",\n children: [\n ui.text(message),\n ui.box({\n padding: \"md\",\n background: \"muted\",\n children: [\n ui.text(JSON.stringify(params, null, 2), { size: \"xs\" }),\n ],\n }),\n ui.row({\n gap: \"md\",\n children: [\n ui.button({\n label: \"Approve\",\n variant: \"success\",\n onClickAction: {\n role: \"user\",\n type: \"action-approved\",\n nextAction,\n data: { token, approvalId },\n ui: ui.text(\"Approval granted\"),\n },\n }),\n ui.button({\n label: \"Cancel\",\n variant: \"outline\",\n onClickAction: {\n type: \"action-rejected\",\n nextAction,\n data: { approvalId },\n },\n }),\n ],\n }),\n ],\n }),\n });\n },\n });\n};\n\n/**\n * Simple HMAC signing using the Web Crypto API (supported in Node 16+ and Browsers).\n */\nasync function signPayload(data: any, secret: string): Promise<string> {\n const msg = JSON.stringify(data);\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const dataToSign = encoder.encode(msg);\n\n const key = await crypto.subtle.importKey(\n \"raw\",\n keyData,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await crypto.subtle.sign(\"HMAC\", key, dataToSign);\n return btoa(String.fromCharCode(...new Uint8Array(signature)));\n}\n"]}
1
+ {"version":3,"sources":["../../src/plugins/require-approval.ts"],"names":[],"mappings":"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","file":"require-approval.js","sourcesContent":["import { plugin } from \"../runtime\";\nimport { ui } from \"../ui\";\nimport type { Action, RuntimeContext } from \"../types\";\n\nexport interface RequireApprovalOptions {\n /**\n * List of action names that require explicit approval.\n * If not provided, all actions will require approval.\n */\n actions?: string[];\n\n /**\n * Optional secret to sign the approval payload.\n * If provided, the plugin will verify that the parameters haven't been\n * tampered with between the request and the approval.\n */\n secret?: string;\n\n /**\n * Custom message to show in the approval card.\n */\n message?: string | ((action: string, params: any) => string);\n\n /**\n * Optional condition to check if approval is needed dynamically.\n */\n shouldApprove?: (\n action: Action<any>,\n params: any,\n context: RuntimeContext\n ) => boolean | Promise<boolean>;\n}\n\n/**\n * A plugin that intercepts actions and requires human approval before execution.\n * It uses SDUI to prompt the user and handles the resumption of the agentic loop.\n */\nexport const requireApproval = (options: RequireApprovalOptions = {}) => {\n return plugin({\n name: \"require-approval\",\n\n /**\n * Step 1: Handle the resumption when the user clicks \"Approve\" or \"Cancel\".\n * We verify the one-time-use approvalId to prevent replay attacks or double-clicks.\n */\n onBeforeRun: async function* ({ event }, context) {\n if (\n event.type === \"action-approved\" ||\n event.type === \"action-rejected\"\n ) {\n const { token, approvalId } = event.data || {};\n const action = event.nextAction?.action;\n const params = event.nextAction?.params;\n\n // 1. Check if this specific request exists and hasn't been used\n const pending = context.state.__pending_approvals?.[approvalId];\n if (!pending) {\n context.suspend({\n role: \"assistant\",\n type: \"error\",\n data: {\n message:\n \"Security Error: This approval request is invalid or has already been used.\",\n },\n ui: ui.card({\n title: \"Security Error\",\n children: [\n ui.text(\n \"This approval request is invalid or has already been used.\"\n ),\n ],\n }),\n });\n }\n\n // 2. Consume the token immediately (Destroy after usage)\n delete context.state.__pending_approvals[approvalId];\n\n if (event.type === \"action-approved\") {\n // 3. Security: Verify the token if a secret was provided\n if (options.secret) {\n const expectedToken = await signPayload(\n { action, params, approvalId },\n options.secret\n );\n if (token !== expectedToken) {\n yield {\n type: \"error\",\n data: {\n message:\n \"Security Warning: Approval token mismatch. Execution blocked.\",\n },\n };\n return;\n }\n }\n\n // 4. Store approval in ephemeral state for the upcoming action execution\n context.state.__approved_action = { action, params };\n\n // No need to return anything here!\n // The Runtime will automatically pick up `event.nextAction`\n // which was attached to the \"action-approved\" event.\n return;\n }\n\n // Handle Rejection\n context.suspend({\n type: \"error\",\n data: {\n message: `Action '${action}' was rejected by the user.`,\n },\n });\n }\n },\n\n /**\n * Step 2: Intercept actions that require approval.\n */\n onBeforeAction: async function* ({ action, params, nextAction }, context) {\n // 1. Check if this action needs approval\n const isTargetAction =\n !options.actions || options.actions.includes(action.name);\n if (!isTargetAction) return;\n\n if (options.shouldApprove) {\n const needsApproval = await options.shouldApprove(\n action,\n params,\n context\n );\n if (!needsApproval) return;\n }\n\n // 2. Check if it was ALREADY approved in this run\n const approval = context.state.__approved_action;\n if (\n approval &&\n approval.action === action.name &&\n JSON.stringify(approval.params) === JSON.stringify(params)\n ) {\n delete context.state.__approved_action;\n return; // Proceed to execution\n }\n\n // 3. Suspend and request approval with a one-time-use nonce\n const approvalId = Math.random().toString(36).substring(2, 15);\n context.state.__pending_approvals =\n context.state.__pending_approvals || {};\n context.state.__pending_approvals[approvalId] = true;\n\n const token = options.secret\n ? await signPayload(\n { action: action.name, params, approvalId },\n options.secret\n )\n : undefined;\n\n const message =\n typeof options.message === \"function\"\n ? options.message(action.name, params)\n : options.message ||\n `The agent wants to execute **${action.name}**. Do you approve?`;\n\n context.suspend({\n type: \"hitl-required\",\n nextAction,\n data: { token, approvalId },\n slot: \"approval\",\n ui: ui.card({\n title: \"Approval Required\",\n children: [\n ui.text(message),\n ui.box({\n padding: \"md\",\n background: \"muted\",\n children: [\n ui.text(JSON.stringify(params, null, 2), { size: \"xs\" }),\n ],\n }),\n ui.row({\n gap: \"md\",\n children: [\n ui.button({\n label: \"Approve\",\n variant: \"success\",\n onClickAction: {\n role: \"user\",\n type: \"action-approved\",\n nextAction,\n data: { token, approvalId },\n ui: ui.text(\"Approval granted\"),\n },\n }),\n ui.button({\n label: \"Cancel\",\n variant: \"outline\",\n onClickAction: {\n type: \"action-rejected\",\n nextAction,\n data: { approvalId },\n },\n }),\n ],\n }),\n ],\n }),\n });\n },\n });\n};\n\n/**\n * Simple HMAC signing using the Web Crypto API (supported in Node 16+ and Browsers).\n */\nasync function signPayload(data: any, secret: string): Promise<string> {\n const msg = JSON.stringify(data);\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const dataToSign = encoder.encode(msg);\n\n const key = await crypto.subtle.importKey(\n \"raw\",\n keyData,\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await crypto.subtle.sign(\"HMAC\", key, dataToSign);\n return btoa(String.fromCharCode(...new Uint8Array(signature)));\n}\n"]}
@@ -1,12 +1,75 @@
1
1
  import z from 'zod';
2
2
 
3
+ /**
4
+ * UI Builder for SDUI.
5
+ * Typed using the UIContract source of truth.
6
+ */
7
+ declare const ui: {
8
+ card: (props: UIContract["card"] & {
9
+ children?: UINode<any>[];
10
+ }) => UINode<"card">;
11
+ row: (props: UIContract["row"] & {
12
+ children?: UINode<any>[];
13
+ }) => UINode<"row">;
14
+ col: (props: UIContract["col"] & {
15
+ children?: UINode<any>[];
16
+ }) => UINode<"col">;
17
+ box: (props: UIContract["box"] & {
18
+ children?: UINode<any>[];
19
+ }) => UINode<"box">;
20
+ spacer: (props: UIContract["spacer"]) => UINode<"spacer">;
21
+ divider: (props: UIContract["divider"]) => UINode<"divider">;
22
+ text: (value: string, props?: Omit<UIContract["text"], "value">) => UINode<"text">;
23
+ heading: (value: string, level?: UIContract["heading"]["level"], props?: Omit<UIContract["heading"], "value" | "level">) => UINode<"heading">;
24
+ badge: (label: string, variant?: UIContract["badge"]["variant"], size?: UISize) => UINode<"badge">;
25
+ image: (src: string, props?: Omit<UIContract["image"], "src">) => UINode<"image">;
26
+ video: (src: string, props?: Omit<UIContract["video"], "src">) => UINode<"video">;
27
+ icon: (name: string, size?: UISize | number, color?: UIColor) => UINode<"icon">;
28
+ chart: (props: UIContract["chart"]) => UINode<"chart">;
29
+ list: (props: UIContract["list"] & {
30
+ children: UINode<any>[];
31
+ }) => UINode<"list">;
32
+ listItem: (props: UIContract["listItem"] & {
33
+ children: UINode<any>[];
34
+ }) => UINode<"listItem">;
35
+ form: (props: UIContract["form"] & {
36
+ children?: UINode<any>[];
37
+ }) => UINode<"form">;
38
+ input: (props: UIContract["input"]) => UINode<"input">;
39
+ textarea: (props: UIContract["textarea"]) => UINode<"textarea">;
40
+ select: (props: UIContract["select"]) => UINode<"select">;
41
+ checkbox: (props: UIContract["checkbox"]) => UINode<"checkbox">;
42
+ hidden: (props: UIContract["hidden"]) => UINode<"hidden">;
43
+ radioGroup: (props: UIContract["radioGroup"]) => UINode<"radioGroup">;
44
+ label: (value: string, props?: Omit<UIContract["label"], "value">) => UINode<"label">;
45
+ colorPicker: (props: UIContract["colorPicker"]) => UINode<"colorPicker">;
46
+ upload: (props: UIContract["upload"]) => UINode<"upload">;
47
+ button: (props: UIContract["button"]) => UINode<"button">;
48
+ float: (props: UIContract["float"] & {
49
+ children?: UINode<any>[];
50
+ }) => UINode<"float">;
51
+ dropdown: (props: UIContract["dropdown"] & {
52
+ children?: UINode<any>[];
53
+ }) => UINode<"dropdown">;
54
+ actions: {
55
+ navigate: (url: string) => Event;
56
+ openUrl: (url: string, target?: string) => Event;
57
+ copy: (text: string) => Event;
58
+ reset: () => Event;
59
+ invalidateQuery: (queryKey: any[]) => Event;
60
+ };
61
+ };
62
+
3
63
  type UISize = "sm" | "md" | "lg";
4
64
  type UIAlign = "start" | "center" | "end" | "stretch";
5
65
  type UIJustify = "start" | "center" | "end" | "between" | "around";
6
66
  type UIWrap = "nowrap" | "wrap" | "wrap-reverse";
7
67
  type UIOrientation = "horizontal" | "vertical";
8
- type UIColor = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "background" | "foreground" | "muted" | "mutedForeground" | "border";
9
- type UISpacing = "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
68
+ type UIColor = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "background" | "foreground" | "muted" | "mutedForeground" | "border" | "transparent";
69
+ type UISpacing = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
70
+ type UIWidth = "auto" | "full" | "min" | "max" | "1/2" | "1/3" | "2/3" | "1/4" | "3/4";
71
+ type UIShadow = "none" | "sm" | "md" | "lg" | "xl";
72
+ type UIRadius = "none" | "sm" | "md" | "lg" | "full";
10
73
  /**
11
74
  * UI Component Contracts
12
75
  * This acts as the source of truth for the SDUI protocol.
@@ -15,31 +78,44 @@ interface UIContract {
15
78
  card: {
16
79
  title?: string;
17
80
  subtitle?: string;
18
- background?: string;
81
+ background?: UIColor;
82
+ padding?: UISpacing;
83
+ radius?: UIRadius;
84
+ shadow?: UIShadow;
19
85
  isLoading?: boolean;
86
+ group?: boolean;
20
87
  };
21
88
  row: {
22
89
  align?: UIAlign;
23
90
  justify?: UIJustify;
24
91
  wrap?: UIWrap;
25
92
  gap?: UISpacing;
93
+ padding?: UISpacing;
94
+ width?: UIWidth;
95
+ group?: boolean;
26
96
  };
27
97
  col: {
28
98
  align?: UIAlign;
29
99
  justify?: UIJustify;
30
100
  gap?: UISpacing;
31
- width?: string | number;
32
- height?: string | number;
101
+ width?: UIWidth;
102
+ height?: "auto" | "full";
33
103
  padding?: UISpacing;
104
+ background?: UIColor;
105
+ radius?: UIRadius;
106
+ group?: boolean;
34
107
  };
35
108
  box: {
36
109
  padding?: UISpacing;
37
- margin?: string | number;
38
- background?: string;
110
+ margin?: UISpacing;
111
+ background?: UIColor;
39
112
  border?: boolean;
40
- borderRadius?: UISpacing;
41
- width?: string | number;
42
- height?: string | number;
113
+ borderColor?: UIColor;
114
+ radius?: UIRadius;
115
+ width?: UIWidth;
116
+ height?: "auto" | "full";
117
+ shadow?: UIShadow;
118
+ group?: boolean;
43
119
  };
44
120
  spacer: {
45
121
  size?: UISpacing;
@@ -48,6 +124,7 @@ interface UIContract {
48
124
  divider: {
49
125
  orientation?: UIOrientation;
50
126
  color?: UIColor;
127
+ margin?: UISpacing;
51
128
  };
52
129
  text: {
53
130
  value: string;
@@ -59,16 +136,21 @@ interface UIContract {
59
136
  heading: {
60
137
  value: string;
61
138
  level?: 1 | 2 | 3 | 4 | 5 | 6;
139
+ color?: UIColor;
140
+ align?: UIAlign;
62
141
  };
63
142
  badge: {
64
143
  label: string;
65
- variant?: "primary" | "secondary" | "success" | "danger" | "warning";
144
+ variant?: "primary" | "secondary" | "success" | "danger" | "warning" | "outline";
66
145
  size?: UISize;
67
146
  };
68
147
  image: {
69
148
  src: string;
70
149
  alt?: string;
71
- size?: UISize;
150
+ width?: UIWidth;
151
+ height?: string | number;
152
+ radius?: UIRadius;
153
+ objectFit?: "cover" | "contain" | "fill";
72
154
  groupId?: string;
73
155
  };
74
156
  video: {
@@ -79,11 +161,12 @@ interface UIContract {
79
161
  loop?: boolean;
80
162
  muted?: boolean;
81
163
  aspectRatio?: "16/9" | "4/3" | "1/1" | "9/16";
82
- width?: string | number;
164
+ width?: UIWidth;
165
+ radius?: UIRadius;
83
166
  };
84
167
  icon: {
85
168
  name: string;
86
- size?: UISize;
169
+ size?: UISize | number;
87
170
  color?: UIColor;
88
171
  };
89
172
  chart: {
@@ -94,22 +177,36 @@ interface UIContract {
94
177
  }>;
95
178
  chartType?: "bar" | "line" | "area" | "pie";
96
179
  title?: string;
180
+ height?: number;
181
+ showValues?: boolean;
182
+ showGrid?: boolean;
183
+ showTooltips?: boolean;
184
+ };
185
+ list: {
186
+ padding?: UISpacing;
187
+ gap?: UISpacing;
97
188
  };
98
- list: {};
99
189
  listItem: {
100
190
  onClickAction?: Event;
101
191
  gap?: UISpacing;
192
+ padding?: UISpacing;
193
+ background?: UIColor;
194
+ radius?: UIRadius;
102
195
  };
103
196
  form: {
104
197
  onSubmitAction?: Event | ((data: any) => Event);
198
+ gap?: UISpacing;
105
199
  };
106
200
  input: {
107
201
  name: string;
108
202
  label?: string;
109
203
  placeholder?: string;
110
204
  defaultValue?: string;
111
- inputType?: string;
205
+ inputType?: "text" | "password" | "email" | "number" | "tel" | "url";
112
206
  onChangeAction?: Event;
207
+ disabled?: boolean;
208
+ required?: boolean;
209
+ width?: UIWidth;
113
210
  };
114
211
  textarea: {
115
212
  name: string;
@@ -118,6 +215,9 @@ interface UIContract {
118
215
  defaultValue?: string;
119
216
  rows?: number;
120
217
  onChangeAction?: Event;
218
+ disabled?: boolean;
219
+ required?: boolean;
220
+ width?: UIWidth;
121
221
  };
122
222
  select: {
123
223
  name: string;
@@ -129,12 +229,16 @@ interface UIContract {
129
229
  defaultValue?: string;
130
230
  placeholder?: string;
131
231
  onChangeAction?: Event;
232
+ disabled?: boolean;
233
+ required?: boolean;
234
+ width?: UIWidth;
132
235
  };
133
236
  checkbox: {
134
237
  name: string;
135
238
  label?: string;
136
239
  checked?: boolean;
137
240
  onChangeAction?: Event;
241
+ disabled?: boolean;
138
242
  };
139
243
  hidden: {
140
244
  name: string;
@@ -151,17 +255,21 @@ interface UIContract {
151
255
  defaultValue?: string;
152
256
  orientation?: UIOrientation;
153
257
  onChangeAction?: Event;
258
+ disabled?: boolean;
154
259
  };
155
260
  label: {
156
261
  value: string;
157
262
  htmlFor?: string;
158
263
  required?: boolean;
264
+ size?: UISpacing;
265
+ color?: UIColor;
159
266
  };
160
267
  colorPicker: {
161
268
  name: string;
162
269
  label?: string;
163
270
  defaultValue?: string;
164
271
  onChangeAction?: Event;
272
+ disabled?: boolean;
165
273
  };
166
274
  upload: {
167
275
  label?: string;
@@ -173,77 +281,44 @@ interface UIContract {
173
281
  }[];
174
282
  onUploadAction?: Event | ((data: any) => Event);
175
283
  mode?: "append" | "replace";
284
+ disabled?: boolean;
176
285
  };
177
286
  button: {
178
- type?: string;
287
+ type?: "button" | "submit" | "reset";
179
288
  label: string;
180
289
  variant?: "primary" | "secondary" | "success" | "danger" | "outline" | "ghost" | "link";
181
290
  size?: UISize;
182
291
  disabled?: boolean;
292
+ width?: UIWidth;
183
293
  onClickAction?: Event;
184
294
  };
295
+ float: {
296
+ position?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center";
297
+ offsetX?: UISpacing;
298
+ offsetY?: UISpacing;
299
+ showOnHover?: boolean;
300
+ };
301
+ dropdown: {
302
+ items: Array<{
303
+ label: string;
304
+ icon?: string;
305
+ onClickAction?: Event;
306
+ }>;
307
+ className?: string;
308
+ triggerClassName?: string;
309
+ };
185
310
  }
186
311
  type UINode<T extends keyof UIContract = keyof UIContract> = {
187
312
  type: T;
188
313
  props?: UIContract[T];
189
314
  children?: UINode<any>[];
190
315
  };
191
- /**
192
- * UI Builder for SDUI.
193
- * Typed using the UIContract source of truth.
194
- */
195
- declare const ui: {
196
- card: (props: UIContract["card"] & {
197
- children?: UINode<any>[];
198
- }) => UINode<"card">;
199
- row: (props: UIContract["row"] & {
200
- children?: UINode<any>[];
201
- }) => UINode<"row">;
202
- col: (props: UIContract["col"] & {
203
- children?: UINode<any>[];
204
- }) => UINode<"col">;
205
- box: (props: UIContract["box"] & {
206
- children?: UINode<any>[];
207
- }) => UINode<"box">;
208
- spacer: (props: UIContract["spacer"]) => UINode<"spacer">;
209
- divider: (props: UIContract["divider"]) => UINode<"divider">;
210
- text: (value: string, props?: Omit<UIContract["text"], "value">) => UINode<"text">;
211
- heading: (value: string, level?: UIContract["heading"]["level"]) => UINode<"heading">;
212
- badge: (label: string, variant?: UIContract["badge"]["variant"], size?: UISize) => UINode<"badge">;
213
- image: (src: string, alt?: string, size?: UISize, groupId?: string) => UINode<"image">;
214
- video: (src: string, props?: Omit<UIContract["video"], "src">) => UINode<"video">;
215
- icon: (name: string, size?: UISize, color?: UIColor) => UINode<"icon">;
216
- chart: (props: UIContract["chart"]) => UINode<"chart">;
217
- list: (children: UINode<any>[]) => UINode<"list">;
218
- listItem: (props: UIContract["listItem"] & {
219
- children: UINode<any>[];
220
- }) => UINode<"listItem">;
221
- form: (props: UIContract["form"] & {
222
- children?: UINode<any>[];
223
- }) => UINode<"form">;
224
- input: (props: UIContract["input"]) => UINode<"input">;
225
- textarea: (props: UIContract["textarea"]) => UINode<"textarea">;
226
- select: (props: UIContract["select"]) => UINode<"select">;
227
- checkbox: (props: UIContract["checkbox"]) => UINode<"checkbox">;
228
- hidden: (props: UIContract["hidden"]) => UINode<"hidden">;
229
- radioGroup: (props: UIContract["radioGroup"]) => UINode<"radioGroup">;
230
- label: (value: string, props?: Omit<UIContract["label"], "value">) => UINode<"label">;
231
- colorPicker: (props: UIContract["colorPicker"]) => UINode<"colorPicker">;
232
- upload: (props: UIContract["upload"]) => UINode<"upload">;
233
- button: (props: UIContract["button"]) => UINode<"button">;
234
- actions: {
235
- navigate: (url: string) => Event;
236
- openUrl: (url: string, target?: string) => Event;
237
- copy: (text: string) => Event;
238
- reset: () => Event;
239
- invalidateQuery: (queryKey: any[]) => Event;
240
- };
241
- };
242
316
  type Role = "user" | "assistant" | "system";
243
317
  type Event = {
244
318
  type: string;
245
319
  data?: any;
246
320
  ui?: UINode;
321
+ surface?: string;
247
322
  slot?: string;
248
323
  runId?: string;
249
324
  threadId?: string;
@@ -366,4 +441,4 @@ interface Config<TState = any> {
366
441
  };
367
442
  }
368
443
 
369
- export { type Action as A, type Brain as B, type Config as C, type Event as E, type HookGenerator as H, type Message as M, type NextAction as N, type Plugin as P, type Role as R, type UISize as U, type UIAlign as a, type UIJustify as b, type UIWrap as c, type UIOrientation as d, type UIColor as e, type UISpacing as f, type UIContract as g, type UINode as h, type ActionExecute as i, type RuntimeContext as j, type Hooks as k, ui as u };
444
+ export { type Action as A, type Brain as B, type Config as C, type Event as E, type HookGenerator as H, type Message as M, type NextAction as N, type Plugin as P, type Role as R, type UISize as U, type UIAlign as a, type UIJustify as b, type UIWrap as c, type UIOrientation as d, type UIColor as e, type UISpacing as f, type UIWidth as g, type UIShadow as h, type UIRadius as i, type UIContract as j, type UINode as k, type ActionExecute as l, type RuntimeContext as m, type Hooks as n, ui as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melony",
3
- "version": "0.1.50",
3
+ "version": "0.1.53",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.ts","../src/runtime.ts"],"names":["event","plugin","action"],"mappings":"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","file":"chunk-IK3OHUHO.js","sourcesContent":["import z from \"zod\";\n\n// ============================================\n// UI Protocol & Contracts\n// ============================================\n\nexport type UISize = \"sm\" | \"md\" | \"lg\";\nexport type UIAlign = \"start\" | \"center\" | \"end\" | \"stretch\";\nexport type UIJustify = \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\nexport type UIWrap = \"nowrap\" | \"wrap\" | \"wrap-reverse\";\nexport type UIOrientation = \"horizontal\" | \"vertical\";\n\nexport type UIColor =\n | \"primary\"\n | \"secondary\"\n | \"success\"\n | \"danger\"\n | \"warning\"\n | \"info\"\n | \"background\"\n | \"foreground\"\n | \"muted\"\n | \"mutedForeground\"\n | \"border\";\n\nexport type UISpacing = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"xxl\";\n\n/**\n * UI Component Contracts\n * This acts as the source of truth for the SDUI protocol.\n */\nexport interface UIContract {\n card: {\n title?: string;\n subtitle?: string;\n background?: string;\n isLoading?: boolean;\n };\n row: {\n align?: UIAlign;\n justify?: UIJustify;\n wrap?: UIWrap;\n gap?: UISpacing;\n };\n col: {\n align?: UIAlign;\n justify?: UIJustify;\n gap?: UISpacing;\n width?: string | number;\n height?: string | number;\n padding?: UISpacing;\n };\n box: {\n padding?: UISpacing;\n margin?: string | number;\n background?: string;\n border?: boolean;\n borderRadius?: UISpacing;\n width?: string | number;\n height?: string | number;\n };\n spacer: {\n size?: UISpacing;\n direction?: UIOrientation;\n };\n divider: {\n orientation?: UIOrientation;\n color?: UIColor;\n };\n text: {\n value: string;\n size?: UISpacing;\n weight?: \"normal\" | \"medium\" | \"semibold\" | \"bold\";\n color?: UIColor;\n align?: UIAlign;\n };\n heading: {\n value: string;\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n };\n badge: {\n label: string;\n variant?: \"primary\" | \"secondary\" | \"success\" | \"danger\" | \"warning\";\n size?: UISize;\n };\n image: {\n src: string;\n alt?: string;\n size?: UISize;\n groupId?: string;\n };\n video: {\n src: string;\n poster?: string;\n autoPlay?: boolean;\n controls?: boolean;\n loop?: boolean;\n muted?: boolean;\n aspectRatio?: \"16/9\" | \"4/3\" | \"1/1\" | \"9/16\";\n width?: string | number;\n };\n icon: {\n name: string;\n size?: UISize;\n color?: UIColor;\n };\n chart: {\n data: Array<{ label: string; value: number; color?: string }>;\n chartType?: \"bar\" | \"line\" | \"area\" | \"pie\";\n title?: string;\n };\n list: {};\n listItem: {\n onClickAction?: Event;\n gap?: UISpacing;\n };\n form: {\n onSubmitAction?: Event | ((data: any) => Event);\n };\n input: {\n name: string;\n label?: string;\n placeholder?: string;\n defaultValue?: string;\n inputType?: string;\n onChangeAction?: Event;\n };\n textarea: {\n name: string;\n label?: string;\n placeholder?: string;\n defaultValue?: string;\n rows?: number;\n onChangeAction?: Event;\n };\n select: {\n name: string;\n label?: string;\n options: Array<{ label: string; value: string }>;\n defaultValue?: string;\n placeholder?: string;\n onChangeAction?: Event;\n };\n checkbox: {\n name: string;\n label?: string;\n checked?: boolean;\n onChangeAction?: Event;\n };\n hidden: {\n name: string;\n value: string;\n };\n radioGroup: {\n name: string;\n options: Array<{ label: string; value: string; disabled?: boolean }>;\n label?: string;\n defaultValue?: string;\n orientation?: UIOrientation;\n onChangeAction?: Event;\n };\n label: {\n value: string;\n htmlFor?: string;\n required?: boolean;\n };\n colorPicker: {\n name: string;\n label?: string;\n defaultValue?: string;\n onChangeAction?: Event;\n };\n upload: {\n label?: string;\n multiple?: boolean;\n accept?: string;\n initialFiles?: { name: string; url: string }[];\n onUploadAction?: Event | ((data: any) => Event);\n mode?: \"append\" | \"replace\";\n };\n button: {\n type?: string;\n label: string;\n variant?:\n | \"primary\"\n | \"secondary\"\n | \"success\"\n | \"danger\"\n | \"outline\"\n | \"ghost\"\n | \"link\";\n size?: UISize;\n disabled?: boolean;\n onClickAction?: Event;\n };\n}\n\nexport type UINode<T extends keyof UIContract = keyof UIContract> = {\n type: T;\n props?: UIContract[T];\n children?: UINode<any>[];\n};\n\n/**\n * UI Builder for SDUI.\n * Typed using the UIContract source of truth.\n */\nexport const ui = {\n card: (\n props: UIContract[\"card\"] & { children?: UINode<any>[] }\n ): UINode<\"card\"> => {\n const { children, ...rest } = props;\n return { type: \"card\", props: rest, children };\n },\n row: (\n props: UIContract[\"row\"] & { children?: UINode<any>[] }\n ): UINode<\"row\"> => {\n const { children, ...rest } = props;\n return { type: \"row\", props: rest, children };\n },\n col: (\n props: UIContract[\"col\"] & { children?: UINode<any>[] }\n ): UINode<\"col\"> => {\n const { children, ...rest } = props;\n return { type: \"col\", props: rest, children };\n },\n box: (\n props: UIContract[\"box\"] & { children?: UINode<any>[] }\n ): UINode<\"box\"> => {\n const { children, ...rest } = props;\n return { type: \"box\", props: rest, children };\n },\n spacer: (props: UIContract[\"spacer\"]): UINode<\"spacer\"> => ({\n type: \"spacer\",\n props,\n }),\n divider: (props: UIContract[\"divider\"]): UINode<\"divider\"> => ({\n type: \"divider\",\n props,\n }),\n text: (\n value: string,\n props?: Omit<UIContract[\"text\"], \"value\">\n ): UINode<\"text\"> => ({\n type: \"text\",\n props: { ...props, value },\n }),\n heading: (\n value: string,\n level: UIContract[\"heading\"][\"level\"] = 1\n ): UINode<\"heading\"> => ({\n type: \"heading\",\n props: { value, level },\n }),\n badge: (\n label: string,\n variant: UIContract[\"badge\"][\"variant\"] = \"primary\",\n size: UISize = \"md\"\n ): UINode<\"badge\"> => ({\n type: \"badge\",\n props: { label, variant, size },\n }),\n image: (\n src: string,\n alt?: string,\n size: UISize = \"md\",\n groupId?: string\n ): UINode<\"image\"> => ({\n type: \"image\",\n props: { src, alt, size, groupId },\n }),\n video: (\n src: string,\n props?: Omit<UIContract[\"video\"], \"src\">\n ): UINode<\"video\"> => ({\n type: \"video\",\n props: { ...props, src },\n }),\n icon: (\n name: string,\n size: UISize = \"md\",\n color?: UIColor\n ): UINode<\"icon\"> => ({\n type: \"icon\",\n props: { name, size, color },\n }),\n chart: (props: UIContract[\"chart\"]): UINode<\"chart\"> => ({\n type: \"chart\",\n props,\n }),\n list: (children: UINode<any>[]): UINode<\"list\"> => ({\n type: \"list\",\n children,\n }),\n listItem: (\n props: UIContract[\"listItem\"] & { children: UINode<any>[] }\n ): UINode<\"listItem\"> => {\n const { children, ...rest } = props;\n return { type: \"listItem\", props: rest, children };\n },\n form: (\n props: UIContract[\"form\"] & { children?: UINode<any>[] }\n ): UINode<\"form\"> => {\n const { children, ...rest } = props;\n return { type: \"form\", props: rest, children };\n },\n input: (props: UIContract[\"input\"]): UINode<\"input\"> => ({\n type: \"input\",\n props,\n }),\n textarea: (props: UIContract[\"textarea\"]): UINode<\"textarea\"> => ({\n type: \"textarea\",\n props,\n }),\n select: (props: UIContract[\"select\"]): UINode<\"select\"> => ({\n type: \"select\",\n props,\n }),\n checkbox: (props: UIContract[\"checkbox\"]): UINode<\"checkbox\"> => ({\n type: \"checkbox\",\n props,\n }),\n hidden: (props: UIContract[\"hidden\"]): UINode<\"hidden\"> => ({\n type: \"hidden\",\n props,\n }),\n radioGroup: (props: UIContract[\"radioGroup\"]): UINode<\"radioGroup\"> => ({\n type: \"radioGroup\",\n props,\n }),\n label: (\n value: string,\n props?: Omit<UIContract[\"label\"], \"value\">\n ): UINode<\"label\"> => ({\n type: \"label\",\n props: { ...props, value },\n }),\n colorPicker: (props: UIContract[\"colorPicker\"]): UINode<\"colorPicker\"> => ({\n type: \"colorPicker\",\n props,\n }),\n upload: (props: UIContract[\"upload\"]): UINode<\"upload\"> => ({\n type: \"upload\",\n props,\n }),\n button: (props: UIContract[\"button\"]): UINode<\"button\"> => ({\n type: \"button\",\n props,\n }),\n actions: {\n navigate: (url: string): Event => ({\n type: \"client:navigate\",\n data: { url },\n }),\n openUrl: (url: string, target = \"_blank\"): Event => ({\n type: \"client:open-url\",\n data: { url, target },\n }),\n copy: (text: string): Event => ({ type: \"client:copy\", data: { text } }),\n reset: (): Event => ({ type: \"client:reset\" }),\n invalidateQuery: (queryKey: any[]): Event => ({\n type: \"client:invalidate-query\",\n data: { queryKey },\n }),\n },\n};\n\n// ============================================\n// Events\n// ============================================\n\nexport type Role = \"user\" | \"assistant\" | \"system\";\n\nexport type Event = {\n type: string;\n data?: any;\n ui?: UINode;\n slot?: string;\n runId?: string;\n threadId?: string;\n threadTitle?: string;\n timestamp?: number;\n role?: Role;\n state?: any;\n /**\n * Optional next action to execute immediately.\n * If provided, the runtime will skip the initial brain dispatch.\n */\n nextAction?: NextAction;\n};\n\nexport interface Message {\n role: Role;\n content: Event[];\n runId?: string;\n threadId?: string;\n}\n\n// ============================================\n// Runtime & Hooks\n// ============================================\n\nexport type ActionExecute<\n TParams extends z.ZodSchema = z.ZodSchema,\n TState = any,\n> = (\n params: z.infer<TParams>,\n context: RuntimeContext<TState>\n) => AsyncGenerator<Event, NextAction | void, unknown>;\n\nexport interface Action<\n TParams extends z.ZodSchema = z.ZodObject<any>,\n TState = any,\n> {\n name: string;\n description?: string;\n paramsSchema: TParams;\n execute: ActionExecute<TParams, TState>;\n}\n\nexport interface NextAction {\n action?: string;\n params?: any;\n description?: string;\n [key: string]: any; // Allow metadata like toolCallId\n}\n\nexport interface RuntimeContext<TState = any> {\n state: TState;\n runId: string;\n stepCount: number;\n actions: Record<string, Action<any, TState>>;\n ui: typeof ui;\n\n /**\n * Immediately interrupts the runtime execution.\n * If an event is provided, it will be emitted before the runtime stops.\n */\n suspend: (event?: Event) => never;\n}\n\n/**\n * Standardized Hook Result.\n * Now a generator to allow yielding multiple events and returning a result.\n */\nexport type HookGenerator<TReturn = void> = AsyncGenerator<\n Event,\n TReturn | void,\n unknown\n>;\n\nexport interface Hooks<TState = any> {\n /**\n * Called when a run session begins.\n * Can yield Events to be emitted, and return a NextAction to jump-start the loop.\n */\n onBeforeRun?: (\n input: { event: Event },\n context: RuntimeContext<TState>\n ) => HookGenerator<NextAction>;\n\n /**\n * Called when a run session completes.\n */\n onAfterRun?: (context: RuntimeContext<TState>) => HookGenerator;\n\n /**\n * Called whenever an event is yielded by the runtime.\n */\n onEvent?: (event: Event, context: RuntimeContext<TState>) => HookGenerator;\n\n /**\n * Called before an action is executed.\n * Yield events to intercept, and return a NextAction to redirect/suspend.\n */\n onBeforeAction?: (\n call: { action: Action<any, TState>; params: any; nextAction: NextAction },\n context: RuntimeContext<TState>\n ) => HookGenerator<NextAction>;\n\n /**\n * Called after an action completes.\n */\n onAfterAction?: (\n result: { action: Action<any, TState>; data: NextAction | void },\n context: RuntimeContext<TState>\n ) => HookGenerator<NextAction>;\n}\n\n/**\n * A plugin is just a named set of hooks.\n */\nexport interface Plugin<TState = any> extends Hooks<TState> {\n name: string;\n}\n\nexport type Brain<TState = any> = (\n event: Event,\n context: RuntimeContext<TState>\n) => AsyncGenerator<Event, NextAction | void, unknown>;\n\nexport interface Config<TState = any> {\n actions: Record<string, Action<any, TState>>;\n /**\n * The central brain for handling incoming events.\n */\n brain?: Brain<TState>;\n hooks?: Hooks<TState>;\n plugins?: Plugin<TState>[];\n safetyMaxSteps?: number;\n starterPrompts?: Array<{\n label: string;\n prompt: string;\n icon?: string;\n }>;\n options?: Array<{\n id: string;\n label: string;\n options: Array<{ id: string; label: string; value: any }>;\n type?: \"single\" | \"multiple\";\n defaultSelectedIds?: string[];\n }>;\n fileAttachments?: {\n enabled?: boolean;\n accept?: string; // e.g., \"image/*,.pdf\" for file input accept attribute\n maxFiles?: number; // Maximum number of files allowed\n maxFileSize?: number; // Maximum file size in bytes\n };\n}\n","import {\n Action,\n Event,\n NextAction,\n RuntimeContext,\n Config,\n Plugin,\n ui,\n HookGenerator,\n} from \"./types\";\nimport { generateId } from \"./utils/generate-id\";\nimport { z } from \"zod\";\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 Slim Runtime.\n * Single Responsibility: Orchestrate Event -> Action -> Event transitions.\n */\nexport class Runtime<TState = any> {\n private config: Config<TState>;\n\n constructor(config: Config<TState>) {\n this.config = config;\n }\n\n public async *run(event: Event): AsyncGenerator<Event> {\n const runId = event.runId ?? generateId();\n\n const context: RuntimeContext<TState> = {\n state: (event.state ?? {}) as TState,\n runId,\n stepCount: 0,\n actions: this.config.actions,\n ui,\n suspend: (event?: Event) => {\n throw event || { type: \"run-suspended\" };\n },\n };\n\n try {\n let nextAction: NextAction | void = undefined;\n\n // 1. Trigger Plugins: onBeforeRun\n for (const plugin of this.config.plugins || []) {\n if (plugin.onBeforeRun) {\n const result = yield* this.callHook(\n plugin.onBeforeRun({ event }, context),\n context\n );\n if (result) {\n nextAction = result as NextAction;\n }\n }\n }\n\n // 2. Trigger Hook: onBeforeRun\n if (this.config.hooks?.onBeforeRun) {\n const result = yield* this.callHook(\n this.config.hooks.onBeforeRun({ event }, context),\n context\n );\n if (result) {\n nextAction = result as NextAction;\n }\n }\n\n // Initial dispatch of the incoming event to the agent's brain\n // Priority:\n // 1. nextAction already set by onBeforeRun hooks\n // 2. nextAction provided in the event itself\n // 3. Dispatch to brain to decide nextAction\n if (!nextAction && event.nextAction) {\n nextAction = event.nextAction;\n }\n\n if (!nextAction && this.config.brain) {\n nextAction = yield* this.dispatchToBrain(event, context);\n }\n\n // Agentic loop\n while (nextAction) {\n if (context.stepCount++ >= (this.config.safetyMaxSteps ?? 10)) {\n yield* this.emit(\n { type: \"error\", data: { message: \"Max steps exceeded\" } },\n context\n );\n break;\n }\n\n const current: NextAction = nextAction;\n nextAction = undefined; // Reset\n\n // 1. Resolve Action\n const actionName: string | undefined = current.action;\n\n if (!actionName) {\n yield* this.emit(\n {\n type: \"error\",\n data: { message: \"No action name provided in NextAction\" },\n },\n context\n );\n break;\n }\n\n const action: Action<any, TState> = this.config.actions[actionName];\n\n if (!action) {\n yield* this.emit(\n {\n type: \"error\",\n data: { message: `Action ${actionName} not found` },\n },\n context\n );\n break;\n }\n\n // 2. Execute Action\n const result = yield* this.executeAction(action, current, context);\n\n // 3. Decide Next Step\n if (this.config.brain) {\n // If we have a brain, feed the result back to it to decide what to do next.\n // This keeps the brain in the loop for multi-step reasoning.\n nextAction = yield* this.dispatchToBrain(\n {\n type: \"action-result\",\n data: {\n ...current, // Preserve all metadata (like toolCallId)\n action: actionName,\n result,\n },\n },\n context\n );\n } else {\n // Simple mode: follow the action's own suggestion for the next step.\n nextAction = result;\n }\n }\n\n // 1. Trigger Plugins: onAfterRun\n for (const plugin of this.config.plugins || []) {\n if (plugin.onAfterRun) {\n yield* this.callHook(plugin.onAfterRun(context), context);\n }\n }\n\n // 2. Trigger Hook: onAfterRun\n if (this.config.hooks?.onAfterRun) {\n yield* this.callHook(this.config.hooks.onAfterRun(context), context);\n }\n } catch (error) {\n let eventToEmit: Event | undefined;\n\n if (isEvent(error)) {\n eventToEmit = error;\n } else {\n // Wrap unexpected errors into an Event\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 };\n }\n\n if (eventToEmit) {\n yield* this.emit(eventToEmit, context);\n }\n\n return; // Gracefully stop the runtime\n }\n }\n\n private async *dispatchToBrain(\n event: Event,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, NextAction | void> {\n const generator = this.config.brain!(event, context);\n while (true) {\n const { value, done } = await generator.next();\n if (done) return value as NextAction | void;\n yield* this.emit(value as Event, context);\n }\n }\n\n private async *executeAction(\n action: Action<any, TState>,\n nextAction: NextAction,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, NextAction | void> {\n const params = nextAction.params;\n\n // 1. Trigger Plugins: onBeforeAction\n for (const plugin of this.config.plugins || []) {\n if (plugin.onBeforeAction) {\n const hookResult = yield* this.callHook(\n plugin.onBeforeAction({ action, params, nextAction }, context),\n context\n );\n if (hookResult) {\n nextAction = hookResult as NextAction;\n }\n }\n }\n\n // 2. Trigger Hook: onBeforeAction\n if (this.config.hooks?.onBeforeAction) {\n const hookResult = yield* this.callHook(\n this.config.hooks.onBeforeAction(\n { action, params, nextAction },\n context\n ),\n context\n );\n if (hookResult) {\n nextAction = hookResult as NextAction;\n }\n }\n\n try {\n const generator = action.execute(params, context);\n let result: NextAction | void;\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) {\n result = value as NextAction | void;\n break;\n }\n yield* this.emit(value as Event, context);\n }\n\n // 3. Trigger Plugins: onAfterAction\n for (const plugin of this.config.plugins || []) {\n if (plugin.onAfterAction) {\n const extra = yield* this.callHook(\n plugin.onAfterAction({ action, data: result }, context),\n context\n );\n if (extra) {\n nextAction = extra as NextAction;\n }\n }\n }\n\n // 4. Trigger Hook: onAfterAction\n if (this.config.hooks?.onAfterAction) {\n const extra = yield* this.callHook(\n this.config.hooks.onAfterAction({ action, data: result }, context),\n context\n );\n if (extra) {\n nextAction = extra as NextAction;\n }\n }\n\n return result;\n } catch (error) {\n if (isEvent(error)) throw error;\n\n throw {\n type: \"error\",\n data: {\n action: action.name,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n };\n }\n }\n\n /**\n * Internal helper to call a hook (generator) and yield its events.\n */\n private async *callHook<T>(\n generator: HookGenerator<T> | undefined,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event, T | void> {\n if (!generator) return;\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) return value as T | void;\n yield* this.emit(value as Event, context);\n }\n }\n\n /**\n * Internal helper to yield an event and trigger the onEvent hook.\n */\n private async *emit(\n event: Event,\n context: RuntimeContext<TState>\n ): AsyncGenerator<Event> {\n const finalEvent = {\n ...event,\n runId: context.runId,\n timestamp: event.timestamp ?? Date.now(),\n role: event.role ?? \"assistant\",\n state: context.state,\n };\n\n // Yield the actual event first\n yield finalEvent;\n\n // 1. Trigger Plugins: onEvent\n for (const plugin of this.config.plugins || []) {\n if (plugin.onEvent) {\n const generator = plugin.onEvent(finalEvent, context);\n for await (const extra of generator) {\n yield { ...extra, runId: context.runId, timestamp: Date.now() };\n }\n }\n }\n\n // 2. Trigger Hook: onEvent for side-effects or extra events\n if (this.config.hooks?.onEvent) {\n const generator = this.config.hooks.onEvent(finalEvent, context);\n for await (const extra of generator) {\n // Yield extra event from hook, ensuring it has required metadata\n yield { ...extra, runId: context.runId, timestamp: Date.now() };\n }\n }\n }\n}\n\nexport const melony = <TState = any>(config: Config<TState>) => {\n const runtime = new Runtime<TState>(config);\n return {\n config,\n run: runtime.run.bind(runtime),\n };\n};\n\n/**\n * Helper to define an action with full type inference.\n */\nexport const action = <T extends z.ZodSchema, TState = any>(\n config: Action<T, TState>\n): Action<T, TState> => config;\n\n/**\n * Helper to define a plugin.\n */\nexport const plugin = <TState = any>(config: Plugin<TState>): Plugin<TState> =>\n config;\n"]}