melony 0.1.54 → 0.1.55
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/dist/chunk-N2OIHGFV.js +138 -0
- package/dist/chunk-N2OIHGFV.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/index.d.ts +17 -3
- package/dist/index.js +281 -3
- package/dist/index.js.map +1 -1
- package/dist/plugins/require-approval.d.ts +1 -1
- package/dist/plugins/require-approval.js +1 -2
- package/dist/plugins/require-approval.js.map +1 -1
- package/dist/{types-CNb-HLkM.d.ts → types-CE5iiNir.d.ts} +1 -0
- package/package.json +1 -1
- package/dist/chunk-EGZ4YTE4.js +0 -388
- package/dist/chunk-EGZ4YTE4.js.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/ui.ts
|
|
2
|
+
var ui = {
|
|
3
|
+
card: (props) => {
|
|
4
|
+
const { children, ...rest } = props;
|
|
5
|
+
return { type: "card", props: rest, children };
|
|
6
|
+
},
|
|
7
|
+
row: (props) => {
|
|
8
|
+
const { children, ...rest } = props;
|
|
9
|
+
return { type: "row", props: rest, children };
|
|
10
|
+
},
|
|
11
|
+
col: (props) => {
|
|
12
|
+
const { children, ...rest } = props;
|
|
13
|
+
return { type: "col", props: rest, children };
|
|
14
|
+
},
|
|
15
|
+
box: (props) => {
|
|
16
|
+
const { children, ...rest } = props;
|
|
17
|
+
return { type: "box", props: rest, children };
|
|
18
|
+
},
|
|
19
|
+
spacer: (props) => ({
|
|
20
|
+
type: "spacer",
|
|
21
|
+
props
|
|
22
|
+
}),
|
|
23
|
+
divider: (props) => ({
|
|
24
|
+
type: "divider",
|
|
25
|
+
props
|
|
26
|
+
}),
|
|
27
|
+
text: (value, props) => ({
|
|
28
|
+
type: "text",
|
|
29
|
+
props: { ...props, value }
|
|
30
|
+
}),
|
|
31
|
+
heading: (value, level = 1, props) => ({
|
|
32
|
+
type: "heading",
|
|
33
|
+
props: { ...props, value, level }
|
|
34
|
+
}),
|
|
35
|
+
badge: (label, variant = "primary", size = "md") => ({
|
|
36
|
+
type: "badge",
|
|
37
|
+
props: { label, variant, size }
|
|
38
|
+
}),
|
|
39
|
+
image: (src, props) => ({
|
|
40
|
+
type: "image",
|
|
41
|
+
props: { ...props, src }
|
|
42
|
+
}),
|
|
43
|
+
video: (src, props) => ({
|
|
44
|
+
type: "video",
|
|
45
|
+
props: { ...props, src }
|
|
46
|
+
}),
|
|
47
|
+
icon: (name, size = "md", color) => ({
|
|
48
|
+
type: "icon",
|
|
49
|
+
props: { name, size, color }
|
|
50
|
+
}),
|
|
51
|
+
chart: (props) => ({
|
|
52
|
+
type: "chart",
|
|
53
|
+
props
|
|
54
|
+
}),
|
|
55
|
+
list: (props) => {
|
|
56
|
+
const { children, ...rest } = props;
|
|
57
|
+
return { type: "list", props: rest, children };
|
|
58
|
+
},
|
|
59
|
+
listItem: (props) => {
|
|
60
|
+
const { children, ...rest } = props;
|
|
61
|
+
return { type: "listItem", props: rest, children };
|
|
62
|
+
},
|
|
63
|
+
form: (props) => {
|
|
64
|
+
const { children, ...rest } = props;
|
|
65
|
+
return { type: "form", props: rest, children };
|
|
66
|
+
},
|
|
67
|
+
input: (props) => ({
|
|
68
|
+
type: "input",
|
|
69
|
+
props
|
|
70
|
+
}),
|
|
71
|
+
textarea: (props) => ({
|
|
72
|
+
type: "textarea",
|
|
73
|
+
props
|
|
74
|
+
}),
|
|
75
|
+
select: (props) => ({
|
|
76
|
+
type: "select",
|
|
77
|
+
props
|
|
78
|
+
}),
|
|
79
|
+
checkbox: (props) => ({
|
|
80
|
+
type: "checkbox",
|
|
81
|
+
props
|
|
82
|
+
}),
|
|
83
|
+
hidden: (props) => ({
|
|
84
|
+
type: "hidden",
|
|
85
|
+
props
|
|
86
|
+
}),
|
|
87
|
+
radioGroup: (props) => ({
|
|
88
|
+
type: "radioGroup",
|
|
89
|
+
props
|
|
90
|
+
}),
|
|
91
|
+
label: (value, props) => ({
|
|
92
|
+
type: "label",
|
|
93
|
+
props: { ...props, value }
|
|
94
|
+
}),
|
|
95
|
+
colorPicker: (props) => ({
|
|
96
|
+
type: "colorPicker",
|
|
97
|
+
props
|
|
98
|
+
}),
|
|
99
|
+
upload: (props) => ({
|
|
100
|
+
type: "upload",
|
|
101
|
+
props
|
|
102
|
+
}),
|
|
103
|
+
button: (props) => ({
|
|
104
|
+
type: "button",
|
|
105
|
+
props
|
|
106
|
+
}),
|
|
107
|
+
float: (props) => {
|
|
108
|
+
const { children, ...rest } = props;
|
|
109
|
+
return { type: "float", props: rest, children };
|
|
110
|
+
},
|
|
111
|
+
dropdown: (props) => {
|
|
112
|
+
const { children, ...rest } = props;
|
|
113
|
+
return { type: "dropdown", props: rest, children };
|
|
114
|
+
},
|
|
115
|
+
actions: {
|
|
116
|
+
navigate: (url) => ({
|
|
117
|
+
type: "client:navigate",
|
|
118
|
+
data: { url }
|
|
119
|
+
}),
|
|
120
|
+
openUrl: (url, target = "_blank") => ({
|
|
121
|
+
type: "client:open-url",
|
|
122
|
+
data: { url, target }
|
|
123
|
+
}),
|
|
124
|
+
copy: (text) => ({ type: "client:copy", data: { text } }),
|
|
125
|
+
reset: () => ({ type: "client:reset" }),
|
|
126
|
+
invalidateQuery: (queryKey) => ({
|
|
127
|
+
type: "client:invalidate-query",
|
|
128
|
+
data: { queryKey }
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/plugin.ts
|
|
134
|
+
var plugin = (config) => config;
|
|
135
|
+
|
|
136
|
+
export { plugin, ui };
|
|
137
|
+
//# sourceMappingURL=chunk-N2OIHGFV.js.map
|
|
138
|
+
//# sourceMappingURL=chunk-N2OIHGFV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui.ts","../src/plugin.ts"],"names":[],"mappings":"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","file":"chunk-N2OIHGFV.js","sourcesContent":["import {\n UIColor,\n UIContract,\n UINode,\n UISize,\n Event,\n UISpacing,\n UIWidth,\n UIRadius,\n} 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: (\n props: UIContract[\"list\"] & { children: UINode<any>[] },\n ): 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 { Plugin } from \"./types\";\n\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
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-
|
|
2
|
-
export { l as ActionExecute,
|
|
1
|
+
import { C as Config, E as Event, A as Action, B as Brain, P as Plugin, M as Message } from './types-CE5iiNir.js';
|
|
2
|
+
export { l as ActionExecute, 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-CE5iiNir.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
export { g as generateId } from './generate-id-DU8kwYc2.js';
|
|
5
5
|
|
|
@@ -22,14 +22,28 @@ declare class Runtime<TState = any> {
|
|
|
22
22
|
*/
|
|
23
23
|
private emit;
|
|
24
24
|
}
|
|
25
|
+
|
|
25
26
|
declare const melony: <TState = any>(config: Config<TState>) => {
|
|
26
27
|
config: Config<TState>;
|
|
27
28
|
run: (event: Event) => AsyncGenerator<Event>;
|
|
28
29
|
};
|
|
30
|
+
|
|
29
31
|
/**
|
|
30
32
|
* Helper to define an action with full type inference.
|
|
31
33
|
*/
|
|
32
34
|
declare const action: <T extends z.ZodSchema, TState = any>(config: Action<T, TState>) => Action<T, TState>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A Cortex is a collection of Brain Regions (Lobes).
|
|
38
|
+
* It delegates events to the appropriate region and coordinates the agentic loop.
|
|
39
|
+
*/
|
|
40
|
+
declare function cortex<TState = any>(regions: Record<string, Brain<TState>>): Brain<TState>;
|
|
41
|
+
/**
|
|
42
|
+
* Helper to define a lobe with full type inference.
|
|
43
|
+
* Lobes are just Brain functions but named for clarity in the biological theme.
|
|
44
|
+
*/
|
|
45
|
+
declare const lobe: <TState = any>(brain: Brain<TState>) => Brain<TState>;
|
|
46
|
+
|
|
33
47
|
/**
|
|
34
48
|
* Helper to define a plugin.
|
|
35
49
|
*/
|
|
@@ -50,4 +64,4 @@ declare function convertEventsToMessages(events: Event[]): Message[];
|
|
|
50
64
|
*/
|
|
51
65
|
declare function filterEventsBySlots(events: Event[]): Event[];
|
|
52
66
|
|
|
53
|
-
export { Action, Config, Event, Message, Plugin, Runtime, action, convertEventsToMessages, createStreamResponse, filterEventsBySlots, melony, plugin };
|
|
67
|
+
export { Action, Brain, Config, Event, Message, Plugin, Runtime, action, convertEventsToMessages, cortex, createStreamResponse, filterEventsBySlots, lobe, melony, plugin };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,284 @@
|
|
|
1
|
-
|
|
2
|
-
export { Runtime, action, melony, plugin, ui } from './chunk-EGZ4YTE4.js';
|
|
1
|
+
import { generateId } from './chunk-WAI5H335.js';
|
|
3
2
|
export { generateId } from './chunk-WAI5H335.js';
|
|
3
|
+
export { createStreamResponse } from './chunk-PDXLHPTX.js';
|
|
4
|
+
import { ui } from './chunk-N2OIHGFV.js';
|
|
5
|
+
export { plugin, ui } from './chunk-N2OIHGFV.js';
|
|
6
|
+
|
|
7
|
+
// src/runtime.ts
|
|
8
|
+
function isEvent(val) {
|
|
9
|
+
return val && typeof val === "object" && typeof val.type === "string";
|
|
10
|
+
}
|
|
11
|
+
var Runtime = class {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
}
|
|
15
|
+
async *run(event) {
|
|
16
|
+
const runId = event.runId ?? generateId();
|
|
17
|
+
const context = {
|
|
18
|
+
state: event.state ?? {},
|
|
19
|
+
runId,
|
|
20
|
+
stepCount: 0,
|
|
21
|
+
actions: this.config.actions,
|
|
22
|
+
ui,
|
|
23
|
+
suspend: (event2) => {
|
|
24
|
+
throw event2 || { type: "run-suspended" };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
let nextAction = void 0;
|
|
29
|
+
for (const plugin2 of this.config.plugins || []) {
|
|
30
|
+
if (plugin2.onBeforeRun) {
|
|
31
|
+
const result = yield* this.callHook(
|
|
32
|
+
plugin2.onBeforeRun({ event }, context),
|
|
33
|
+
context
|
|
34
|
+
);
|
|
35
|
+
if (result) {
|
|
36
|
+
nextAction = result;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (this.config.hooks?.onBeforeRun) {
|
|
41
|
+
const result = yield* this.callHook(
|
|
42
|
+
this.config.hooks.onBeforeRun({ event }, context),
|
|
43
|
+
context
|
|
44
|
+
);
|
|
45
|
+
if (result) {
|
|
46
|
+
nextAction = result;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!nextAction && event.nextAction) {
|
|
50
|
+
nextAction = event.nextAction;
|
|
51
|
+
}
|
|
52
|
+
if (!nextAction && this.config.brain) {
|
|
53
|
+
nextAction = yield* this.dispatchToBrain(event, context);
|
|
54
|
+
}
|
|
55
|
+
while (nextAction) {
|
|
56
|
+
if (context.stepCount++ >= (this.config.safetyMaxSteps ?? 10)) {
|
|
57
|
+
yield* this.emit(
|
|
58
|
+
{ type: "error", data: { message: "Max steps exceeded" } },
|
|
59
|
+
context
|
|
60
|
+
);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
const current = nextAction;
|
|
64
|
+
nextAction = void 0;
|
|
65
|
+
const actionName = current.action;
|
|
66
|
+
if (!actionName) {
|
|
67
|
+
yield* this.emit(
|
|
68
|
+
{
|
|
69
|
+
type: "error",
|
|
70
|
+
data: { message: "No action name provided in NextAction" }
|
|
71
|
+
},
|
|
72
|
+
context
|
|
73
|
+
);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
const action2 = this.config.actions[actionName];
|
|
77
|
+
if (!action2) {
|
|
78
|
+
yield* this.emit(
|
|
79
|
+
{
|
|
80
|
+
type: "error",
|
|
81
|
+
data: { message: `Action ${actionName} not found` }
|
|
82
|
+
},
|
|
83
|
+
context
|
|
84
|
+
);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const result = yield* this.executeAction(action2, current, context);
|
|
88
|
+
if (this.config.brain) {
|
|
89
|
+
nextAction = yield* this.dispatchToBrain(
|
|
90
|
+
{
|
|
91
|
+
type: "action-result",
|
|
92
|
+
data: {
|
|
93
|
+
...current,
|
|
94
|
+
// Preserve all metadata (like toolCallId)
|
|
95
|
+
action: actionName,
|
|
96
|
+
result
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
context
|
|
100
|
+
);
|
|
101
|
+
} else {
|
|
102
|
+
nextAction = result;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const plugin2 of this.config.plugins || []) {
|
|
106
|
+
if (plugin2.onAfterRun) {
|
|
107
|
+
yield* this.callHook(plugin2.onAfterRun(context), context);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (this.config.hooks?.onAfterRun) {
|
|
111
|
+
yield* this.callHook(this.config.hooks.onAfterRun(context), context);
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
let eventToEmit;
|
|
115
|
+
if (isEvent(error)) {
|
|
116
|
+
eventToEmit = error;
|
|
117
|
+
} else {
|
|
118
|
+
eventToEmit = {
|
|
119
|
+
type: "error",
|
|
120
|
+
data: {
|
|
121
|
+
message: error instanceof Error ? error.message : String(error),
|
|
122
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (eventToEmit) {
|
|
127
|
+
yield* this.emit(eventToEmit, context);
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async *dispatchToBrain(event, context) {
|
|
133
|
+
const generator = this.config.brain(event, context);
|
|
134
|
+
while (true) {
|
|
135
|
+
const { value, done } = await generator.next();
|
|
136
|
+
if (done) return value;
|
|
137
|
+
yield* this.emit(value, context);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async *executeAction(action2, nextAction, context) {
|
|
141
|
+
const params = nextAction.params;
|
|
142
|
+
for (const plugin2 of this.config.plugins || []) {
|
|
143
|
+
if (plugin2.onBeforeAction) {
|
|
144
|
+
const hookResult = yield* this.callHook(
|
|
145
|
+
plugin2.onBeforeAction({ action: action2, params, nextAction }, context),
|
|
146
|
+
context
|
|
147
|
+
);
|
|
148
|
+
if (hookResult) {
|
|
149
|
+
nextAction = hookResult;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (this.config.hooks?.onBeforeAction) {
|
|
154
|
+
const hookResult = yield* this.callHook(
|
|
155
|
+
this.config.hooks.onBeforeAction(
|
|
156
|
+
{ action: action2, params, nextAction },
|
|
157
|
+
context
|
|
158
|
+
),
|
|
159
|
+
context
|
|
160
|
+
);
|
|
161
|
+
if (hookResult) {
|
|
162
|
+
nextAction = hookResult;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const generator = action2.execute(params, context);
|
|
167
|
+
let result;
|
|
168
|
+
while (true) {
|
|
169
|
+
const { value, done } = await generator.next();
|
|
170
|
+
if (done) {
|
|
171
|
+
result = value;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
yield* this.emit(value, context);
|
|
175
|
+
}
|
|
176
|
+
for (const plugin2 of this.config.plugins || []) {
|
|
177
|
+
if (plugin2.onAfterAction) {
|
|
178
|
+
const extra = yield* this.callHook(
|
|
179
|
+
plugin2.onAfterAction({ action: action2, data: result }, context),
|
|
180
|
+
context
|
|
181
|
+
);
|
|
182
|
+
if (extra) {
|
|
183
|
+
nextAction = extra;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (this.config.hooks?.onAfterAction) {
|
|
188
|
+
const extra = yield* this.callHook(
|
|
189
|
+
this.config.hooks.onAfterAction({ action: action2, data: result }, context),
|
|
190
|
+
context
|
|
191
|
+
);
|
|
192
|
+
if (extra) {
|
|
193
|
+
nextAction = extra;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
if (isEvent(error)) throw error;
|
|
199
|
+
throw {
|
|
200
|
+
type: "error",
|
|
201
|
+
data: {
|
|
202
|
+
action: action2.name,
|
|
203
|
+
message: error instanceof Error ? error.message : String(error),
|
|
204
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Internal helper to call a hook (generator) and yield its events.
|
|
211
|
+
*/
|
|
212
|
+
async *callHook(generator, context) {
|
|
213
|
+
if (!generator) return;
|
|
214
|
+
while (true) {
|
|
215
|
+
const { value, done } = await generator.next();
|
|
216
|
+
if (done) return value;
|
|
217
|
+
yield* this.emit(value, context);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Internal helper to yield an event and trigger the onEvent hook.
|
|
222
|
+
*/
|
|
223
|
+
async *emit(event, context) {
|
|
224
|
+
const finalEvent = {
|
|
225
|
+
...event,
|
|
226
|
+
runId: context.runId,
|
|
227
|
+
timestamp: event.timestamp ?? Date.now(),
|
|
228
|
+
role: event.role ?? "assistant",
|
|
229
|
+
state: context.state
|
|
230
|
+
};
|
|
231
|
+
yield finalEvent;
|
|
232
|
+
for (const plugin2 of this.config.plugins || []) {
|
|
233
|
+
if (plugin2.onEvent) {
|
|
234
|
+
const generator = plugin2.onEvent(finalEvent, context);
|
|
235
|
+
for await (const extra of generator) {
|
|
236
|
+
yield { ...extra, runId: context.runId, timestamp: Date.now() };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (this.config.hooks?.onEvent) {
|
|
241
|
+
const generator = this.config.hooks.onEvent(finalEvent, context);
|
|
242
|
+
for await (const extra of generator) {
|
|
243
|
+
yield { ...extra, runId: context.runId, timestamp: Date.now() };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/melony.ts
|
|
250
|
+
var melony = (config) => {
|
|
251
|
+
const runtime = new Runtime(config);
|
|
252
|
+
return {
|
|
253
|
+
config,
|
|
254
|
+
run: runtime.run.bind(runtime)
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// src/action.ts
|
|
259
|
+
var action = (config) => config;
|
|
260
|
+
|
|
261
|
+
// src/cortex.ts
|
|
262
|
+
function cortex(regions) {
|
|
263
|
+
return async function* (event, context) {
|
|
264
|
+
for (const [name, region] of Object.entries(regions)) {
|
|
265
|
+
const generator = region(event, context);
|
|
266
|
+
while (true) {
|
|
267
|
+
const { value, done } = await generator.next();
|
|
268
|
+
if (done) {
|
|
269
|
+
if (value) return value;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
yield {
|
|
273
|
+
...value,
|
|
274
|
+
metadata: { ...value.metadata, region: name }
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
var lobe = (brain) => brain;
|
|
4
282
|
|
|
5
283
|
// src/utils/convert-events-to-messages.ts
|
|
6
284
|
function convertEventsToMessages(events) {
|
|
@@ -53,6 +331,6 @@ function filterEventsBySlots(events) {
|
|
|
53
331
|
return result;
|
|
54
332
|
}
|
|
55
333
|
|
|
56
|
-
export { convertEventsToMessages, filterEventsBySlots };
|
|
334
|
+
export { Runtime, action, convertEventsToMessages, cortex, filterEventsBySlots, lobe, melony };
|
|
57
335
|
//# sourceMappingURL=index.js.map
|
|
58
336
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
+
{"version":3,"sources":["../src/runtime.ts","../src/melony.ts","../src/action.ts","../src/cortex.ts","../src/utils/convert-events-to-messages.ts","../src/utils/filter-events-by-slots.ts"],"names":["event","plugin","action"],"mappings":"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","file":"index.js","sourcesContent":["import {\n Action,\n Event,\n NextAction,\n RuntimeContext,\n Config,\n HookGenerator,\n} from \"./types\";\nimport { ui } from \"./ui\";\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 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}","import { Runtime } from \"./runtime\";\nimport { Config } from \"./types\";\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};","import { z } from 'zod'\nimport { Action } from './types';\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","import { Brain, Event, RuntimeContext } from \"./types\";\n\n/**\n * A Cortex is a collection of Brain Regions (Lobes).\n * It delegates events to the appropriate region and coordinates the agentic loop.\n */\nexport function cortex<TState = any>(\n regions: Record<string, Brain<TState>>,\n): Brain<TState> {\n return async function* (event: Event, context: RuntimeContext<TState>) {\n // We iterate through all regions sequentially.\n for (const [name, region] of Object.entries(regions)) {\n const generator = region(event, context);\n\n while (true) {\n const { value, done } = await generator.next();\n\n if (done) {\n // If a region returns a NextAction, that region has \"taken control\"\n // of the executive function. We return it to the runtime.\n if (value) return value;\n break;\n }\n\n // Yield events from the region (text, UI, etc.)\n // We tag them with the region name in metadata.\n yield {\n ...value,\n metadata: { ...value.metadata, region: name },\n };\n }\n }\n\n // If no region returns a NextAction, the brain is \"resting.\"\n return;\n };\n}\n\n/**\n * Helper to define a lobe with full type inference.\n * Lobes are just Brain functions but named for clarity in the biological theme.\n */\nexport const lobe = <TState = any>(brain: Brain<TState>): Brain<TState> => brain;\n","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 +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 \"../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
|
+
{"version":3,"sources":["../../src/plugins/require-approval.ts"],"names":[],"mappings":"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","file":"require-approval.js","sourcesContent":["import { plugin } from \"../plugin\";\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"]}
|
package/package.json
CHANGED
package/dist/chunk-EGZ4YTE4.js
DELETED
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
import { generateId } from './chunk-WAI5H335.js';
|
|
2
|
-
|
|
3
|
-
// src/ui.ts
|
|
4
|
-
var ui = {
|
|
5
|
-
card: (props) => {
|
|
6
|
-
const { children, ...rest } = props;
|
|
7
|
-
return { type: "card", props: rest, children };
|
|
8
|
-
},
|
|
9
|
-
row: (props) => {
|
|
10
|
-
const { children, ...rest } = props;
|
|
11
|
-
return { type: "row", props: rest, children };
|
|
12
|
-
},
|
|
13
|
-
col: (props) => {
|
|
14
|
-
const { children, ...rest } = props;
|
|
15
|
-
return { type: "col", props: rest, children };
|
|
16
|
-
},
|
|
17
|
-
box: (props) => {
|
|
18
|
-
const { children, ...rest } = props;
|
|
19
|
-
return { type: "box", props: rest, children };
|
|
20
|
-
},
|
|
21
|
-
spacer: (props) => ({
|
|
22
|
-
type: "spacer",
|
|
23
|
-
props
|
|
24
|
-
}),
|
|
25
|
-
divider: (props) => ({
|
|
26
|
-
type: "divider",
|
|
27
|
-
props
|
|
28
|
-
}),
|
|
29
|
-
text: (value, props) => ({
|
|
30
|
-
type: "text",
|
|
31
|
-
props: { ...props, value }
|
|
32
|
-
}),
|
|
33
|
-
heading: (value, level = 1, props) => ({
|
|
34
|
-
type: "heading",
|
|
35
|
-
props: { ...props, value, level }
|
|
36
|
-
}),
|
|
37
|
-
badge: (label, variant = "primary", size = "md") => ({
|
|
38
|
-
type: "badge",
|
|
39
|
-
props: { label, variant, size }
|
|
40
|
-
}),
|
|
41
|
-
image: (src, props) => ({
|
|
42
|
-
type: "image",
|
|
43
|
-
props: { ...props, src }
|
|
44
|
-
}),
|
|
45
|
-
video: (src, props) => ({
|
|
46
|
-
type: "video",
|
|
47
|
-
props: { ...props, src }
|
|
48
|
-
}),
|
|
49
|
-
icon: (name, size = "md", color) => ({
|
|
50
|
-
type: "icon",
|
|
51
|
-
props: { name, size, color }
|
|
52
|
-
}),
|
|
53
|
-
chart: (props) => ({
|
|
54
|
-
type: "chart",
|
|
55
|
-
props
|
|
56
|
-
}),
|
|
57
|
-
list: (props) => {
|
|
58
|
-
const { children, ...rest } = props;
|
|
59
|
-
return { type: "list", props: rest, children };
|
|
60
|
-
},
|
|
61
|
-
listItem: (props) => {
|
|
62
|
-
const { children, ...rest } = props;
|
|
63
|
-
return { type: "listItem", props: rest, children };
|
|
64
|
-
},
|
|
65
|
-
form: (props) => {
|
|
66
|
-
const { children, ...rest } = props;
|
|
67
|
-
return { type: "form", props: rest, children };
|
|
68
|
-
},
|
|
69
|
-
input: (props) => ({
|
|
70
|
-
type: "input",
|
|
71
|
-
props
|
|
72
|
-
}),
|
|
73
|
-
textarea: (props) => ({
|
|
74
|
-
type: "textarea",
|
|
75
|
-
props
|
|
76
|
-
}),
|
|
77
|
-
select: (props) => ({
|
|
78
|
-
type: "select",
|
|
79
|
-
props
|
|
80
|
-
}),
|
|
81
|
-
checkbox: (props) => ({
|
|
82
|
-
type: "checkbox",
|
|
83
|
-
props
|
|
84
|
-
}),
|
|
85
|
-
hidden: (props) => ({
|
|
86
|
-
type: "hidden",
|
|
87
|
-
props
|
|
88
|
-
}),
|
|
89
|
-
radioGroup: (props) => ({
|
|
90
|
-
type: "radioGroup",
|
|
91
|
-
props
|
|
92
|
-
}),
|
|
93
|
-
label: (value, props) => ({
|
|
94
|
-
type: "label",
|
|
95
|
-
props: { ...props, value }
|
|
96
|
-
}),
|
|
97
|
-
colorPicker: (props) => ({
|
|
98
|
-
type: "colorPicker",
|
|
99
|
-
props
|
|
100
|
-
}),
|
|
101
|
-
upload: (props) => ({
|
|
102
|
-
type: "upload",
|
|
103
|
-
props
|
|
104
|
-
}),
|
|
105
|
-
button: (props) => ({
|
|
106
|
-
type: "button",
|
|
107
|
-
props
|
|
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
|
-
},
|
|
117
|
-
actions: {
|
|
118
|
-
navigate: (url) => ({
|
|
119
|
-
type: "client:navigate",
|
|
120
|
-
data: { url }
|
|
121
|
-
}),
|
|
122
|
-
openUrl: (url, target = "_blank") => ({
|
|
123
|
-
type: "client:open-url",
|
|
124
|
-
data: { url, target }
|
|
125
|
-
}),
|
|
126
|
-
copy: (text) => ({ type: "client:copy", data: { text } }),
|
|
127
|
-
reset: () => ({ type: "client:reset" }),
|
|
128
|
-
invalidateQuery: (queryKey) => ({
|
|
129
|
-
type: "client:invalidate-query",
|
|
130
|
-
data: { queryKey }
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// src/runtime.ts
|
|
136
|
-
function isEvent(val) {
|
|
137
|
-
return val && typeof val === "object" && typeof val.type === "string";
|
|
138
|
-
}
|
|
139
|
-
var Runtime = class {
|
|
140
|
-
constructor(config) {
|
|
141
|
-
this.config = config;
|
|
142
|
-
}
|
|
143
|
-
async *run(event) {
|
|
144
|
-
const runId = event.runId ?? generateId();
|
|
145
|
-
const context = {
|
|
146
|
-
state: event.state ?? {},
|
|
147
|
-
runId,
|
|
148
|
-
stepCount: 0,
|
|
149
|
-
actions: this.config.actions,
|
|
150
|
-
ui,
|
|
151
|
-
suspend: (event2) => {
|
|
152
|
-
throw event2 || { type: "run-suspended" };
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
try {
|
|
156
|
-
let nextAction = void 0;
|
|
157
|
-
for (const plugin2 of this.config.plugins || []) {
|
|
158
|
-
if (plugin2.onBeforeRun) {
|
|
159
|
-
const result = yield* this.callHook(
|
|
160
|
-
plugin2.onBeforeRun({ event }, context),
|
|
161
|
-
context
|
|
162
|
-
);
|
|
163
|
-
if (result) {
|
|
164
|
-
nextAction = result;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (this.config.hooks?.onBeforeRun) {
|
|
169
|
-
const result = yield* this.callHook(
|
|
170
|
-
this.config.hooks.onBeforeRun({ event }, context),
|
|
171
|
-
context
|
|
172
|
-
);
|
|
173
|
-
if (result) {
|
|
174
|
-
nextAction = result;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (!nextAction && event.nextAction) {
|
|
178
|
-
nextAction = event.nextAction;
|
|
179
|
-
}
|
|
180
|
-
if (!nextAction && this.config.brain) {
|
|
181
|
-
nextAction = yield* this.dispatchToBrain(event, context);
|
|
182
|
-
}
|
|
183
|
-
while (nextAction) {
|
|
184
|
-
if (context.stepCount++ >= (this.config.safetyMaxSteps ?? 10)) {
|
|
185
|
-
yield* this.emit(
|
|
186
|
-
{ type: "error", data: { message: "Max steps exceeded" } },
|
|
187
|
-
context
|
|
188
|
-
);
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
const current = nextAction;
|
|
192
|
-
nextAction = void 0;
|
|
193
|
-
const actionName = current.action;
|
|
194
|
-
if (!actionName) {
|
|
195
|
-
yield* this.emit(
|
|
196
|
-
{
|
|
197
|
-
type: "error",
|
|
198
|
-
data: { message: "No action name provided in NextAction" }
|
|
199
|
-
},
|
|
200
|
-
context
|
|
201
|
-
);
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
const action2 = this.config.actions[actionName];
|
|
205
|
-
if (!action2) {
|
|
206
|
-
yield* this.emit(
|
|
207
|
-
{
|
|
208
|
-
type: "error",
|
|
209
|
-
data: { message: `Action ${actionName} not found` }
|
|
210
|
-
},
|
|
211
|
-
context
|
|
212
|
-
);
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
const result = yield* this.executeAction(action2, current, context);
|
|
216
|
-
if (this.config.brain) {
|
|
217
|
-
nextAction = yield* this.dispatchToBrain(
|
|
218
|
-
{
|
|
219
|
-
type: "action-result",
|
|
220
|
-
data: {
|
|
221
|
-
...current,
|
|
222
|
-
// Preserve all metadata (like toolCallId)
|
|
223
|
-
action: actionName,
|
|
224
|
-
result
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
context
|
|
228
|
-
);
|
|
229
|
-
} else {
|
|
230
|
-
nextAction = result;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
for (const plugin2 of this.config.plugins || []) {
|
|
234
|
-
if (plugin2.onAfterRun) {
|
|
235
|
-
yield* this.callHook(plugin2.onAfterRun(context), context);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (this.config.hooks?.onAfterRun) {
|
|
239
|
-
yield* this.callHook(this.config.hooks.onAfterRun(context), context);
|
|
240
|
-
}
|
|
241
|
-
} catch (error) {
|
|
242
|
-
let eventToEmit;
|
|
243
|
-
if (isEvent(error)) {
|
|
244
|
-
eventToEmit = error;
|
|
245
|
-
} else {
|
|
246
|
-
eventToEmit = {
|
|
247
|
-
type: "error",
|
|
248
|
-
data: {
|
|
249
|
-
message: error instanceof Error ? error.message : String(error),
|
|
250
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
if (eventToEmit) {
|
|
255
|
-
yield* this.emit(eventToEmit, context);
|
|
256
|
-
}
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
async *dispatchToBrain(event, context) {
|
|
261
|
-
const generator = this.config.brain(event, context);
|
|
262
|
-
while (true) {
|
|
263
|
-
const { value, done } = await generator.next();
|
|
264
|
-
if (done) return value;
|
|
265
|
-
yield* this.emit(value, context);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
async *executeAction(action2, nextAction, context) {
|
|
269
|
-
const params = nextAction.params;
|
|
270
|
-
for (const plugin2 of this.config.plugins || []) {
|
|
271
|
-
if (plugin2.onBeforeAction) {
|
|
272
|
-
const hookResult = yield* this.callHook(
|
|
273
|
-
plugin2.onBeforeAction({ action: action2, params, nextAction }, context),
|
|
274
|
-
context
|
|
275
|
-
);
|
|
276
|
-
if (hookResult) {
|
|
277
|
-
nextAction = hookResult;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (this.config.hooks?.onBeforeAction) {
|
|
282
|
-
const hookResult = yield* this.callHook(
|
|
283
|
-
this.config.hooks.onBeforeAction(
|
|
284
|
-
{ action: action2, params, nextAction },
|
|
285
|
-
context
|
|
286
|
-
),
|
|
287
|
-
context
|
|
288
|
-
);
|
|
289
|
-
if (hookResult) {
|
|
290
|
-
nextAction = hookResult;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
try {
|
|
294
|
-
const generator = action2.execute(params, context);
|
|
295
|
-
let result;
|
|
296
|
-
while (true) {
|
|
297
|
-
const { value, done } = await generator.next();
|
|
298
|
-
if (done) {
|
|
299
|
-
result = value;
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
yield* this.emit(value, context);
|
|
303
|
-
}
|
|
304
|
-
for (const plugin2 of this.config.plugins || []) {
|
|
305
|
-
if (plugin2.onAfterAction) {
|
|
306
|
-
const extra = yield* this.callHook(
|
|
307
|
-
plugin2.onAfterAction({ action: action2, data: result }, context),
|
|
308
|
-
context
|
|
309
|
-
);
|
|
310
|
-
if (extra) {
|
|
311
|
-
nextAction = extra;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
if (this.config.hooks?.onAfterAction) {
|
|
316
|
-
const extra = yield* this.callHook(
|
|
317
|
-
this.config.hooks.onAfterAction({ action: action2, data: result }, context),
|
|
318
|
-
context
|
|
319
|
-
);
|
|
320
|
-
if (extra) {
|
|
321
|
-
nextAction = extra;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
return result;
|
|
325
|
-
} catch (error) {
|
|
326
|
-
if (isEvent(error)) throw error;
|
|
327
|
-
throw {
|
|
328
|
-
type: "error",
|
|
329
|
-
data: {
|
|
330
|
-
action: action2.name,
|
|
331
|
-
message: error instanceof Error ? error.message : String(error),
|
|
332
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Internal helper to call a hook (generator) and yield its events.
|
|
339
|
-
*/
|
|
340
|
-
async *callHook(generator, context) {
|
|
341
|
-
if (!generator) return;
|
|
342
|
-
while (true) {
|
|
343
|
-
const { value, done } = await generator.next();
|
|
344
|
-
if (done) return value;
|
|
345
|
-
yield* this.emit(value, context);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Internal helper to yield an event and trigger the onEvent hook.
|
|
350
|
-
*/
|
|
351
|
-
async *emit(event, context) {
|
|
352
|
-
const finalEvent = {
|
|
353
|
-
...event,
|
|
354
|
-
runId: context.runId,
|
|
355
|
-
timestamp: event.timestamp ?? Date.now(),
|
|
356
|
-
role: event.role ?? "assistant",
|
|
357
|
-
state: context.state
|
|
358
|
-
};
|
|
359
|
-
yield finalEvent;
|
|
360
|
-
for (const plugin2 of this.config.plugins || []) {
|
|
361
|
-
if (plugin2.onEvent) {
|
|
362
|
-
const generator = plugin2.onEvent(finalEvent, context);
|
|
363
|
-
for await (const extra of generator) {
|
|
364
|
-
yield { ...extra, runId: context.runId, timestamp: Date.now() };
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (this.config.hooks?.onEvent) {
|
|
369
|
-
const generator = this.config.hooks.onEvent(finalEvent, context);
|
|
370
|
-
for await (const extra of generator) {
|
|
371
|
-
yield { ...extra, runId: context.runId, timestamp: Date.now() };
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
var melony = (config) => {
|
|
377
|
-
const runtime = new Runtime(config);
|
|
378
|
-
return {
|
|
379
|
-
config,
|
|
380
|
-
run: runtime.run.bind(runtime)
|
|
381
|
-
};
|
|
382
|
-
};
|
|
383
|
-
var action = (config) => config;
|
|
384
|
-
var plugin = (config) => config;
|
|
385
|
-
|
|
386
|
-
export { Runtime, action, melony, plugin, ui };
|
|
387
|
-
//# sourceMappingURL=chunk-EGZ4YTE4.js.map
|
|
388
|
-
//# sourceMappingURL=chunk-EGZ4YTE4.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui.ts","../src/runtime.ts"],"names":["event","plugin","action"],"mappings":";;;AAeO,IAAM,EAAA,GAAK;AAAA,EAChB,IAAA,EAAM,CACJ,KAAA,KACmB;AACnB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC/C,CAAA;AAAA,EACA,GAAA,EAAK,CACH,KAAA,KACkB;AAClB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC9C,CAAA;AAAA,EACA,GAAA,EAAK,CACH,KAAA,KACkB;AAClB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC9C,CAAA;AAAA,EACA,GAAA,EAAK,CACH,KAAA,KACkB;AAClB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC9C,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,KAAA,MAAmD;AAAA,IAC1D,IAAA,EAAM,QAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,OAAA,EAAS,CAAC,KAAA,MAAqD;AAAA,IAC7D,IAAA,EAAM,SAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,IAAA,EAAM,CACJ,KAAA,EACA,KAAA,MACoB;AAAA,IACpB,IAAA,EAAM,MAAA;AAAA,IACN,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,KAAA;AAAM,GAC3B,CAAA;AAAA,EACA,OAAA,EAAS,CACP,KAAA,EACA,KAAA,GAAwC,GACxC,KAAA,MACuB;AAAA,IACvB,IAAA,EAAM,SAAA;AAAA,IACN,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,OAAO,KAAA;AAAM,GAClC,CAAA;AAAA,EACA,OAAO,CACL,KAAA,EACA,OAAA,GAA0C,SAAA,EAC1C,OAAe,IAAA,MACM;AAAA,IACrB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA,EAAO,EAAE,KAAA,EAAO,OAAA,EAAS,IAAA;AAAK,GAChC,CAAA;AAAA,EACA,KAAA,EAAO,CACL,GAAA,EACA,KAAA,MACqB;AAAA,IACrB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,GAAA;AAAI,GACzB,CAAA;AAAA,EACA,KAAA,EAAO,CACL,GAAA,EACA,KAAA,MACqB;AAAA,IACrB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,GAAA;AAAI,GACzB,CAAA;AAAA,EACA,IAAA,EAAM,CACJ,IAAA,EACA,IAAA,GAAwB,MACxB,KAAA,MACoB;AAAA,IACpB,IAAA,EAAM,MAAA;AAAA,IACN,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA;AAAM,GAC7B,CAAA;AAAA,EACA,KAAA,EAAO,CAAC,KAAA,MAAiD;AAAA,IACvD,IAAA,EAAM,OAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,IAAA,EAAM,CACJ,KAAA,KACmB;AACnB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC/C,CAAA;AAAA,EACA,QAAA,EAAU,CACR,KAAA,KACuB;AACvB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EACnD,CAAA;AAAA,EACA,IAAA,EAAM,CACJ,KAAA,KACmB;AACnB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAC/C,CAAA;AAAA,EACA,KAAA,EAAO,CAAC,KAAA,MAAiD;AAAA,IACvD,IAAA,EAAM,OAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,QAAA,EAAU,CAAC,KAAA,MAAuD;AAAA,IAChE,IAAA,EAAM,UAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,KAAA,MAAmD;AAAA,IAC1D,IAAA,EAAM,QAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,QAAA,EAAU,CAAC,KAAA,MAAuD;AAAA,IAChE,IAAA,EAAM,UAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,KAAA,MAAmD;AAAA,IAC1D,IAAA,EAAM,QAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,UAAA,EAAY,CAAC,KAAA,MAA2D;AAAA,IACtE,IAAA,EAAM,YAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,KAAA,EAAO,CACL,KAAA,EACA,KAAA,MACqB;AAAA,IACrB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,KAAA;AAAM,GAC3B,CAAA;AAAA,EACA,WAAA,EAAa,CAAC,KAAA,MAA6D;AAAA,IACzE,IAAA,EAAM,aAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,KAAA,MAAmD;AAAA,IAC1D,IAAA,EAAM,QAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,MAAA,EAAQ,CAAC,KAAA,MAAmD;AAAA,IAC1D,IAAA,EAAM,QAAA;AAAA,IACN;AAAA,GACF,CAAA;AAAA,EACA,KAAA,EAAO,CACL,KAAA,KACoB;AACpB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EAChD,CAAA;AAAA,EACA,QAAA,EAAU,CACR,KAAA,KACuB;AACvB,IAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,IAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,MAAM,QAAA,EAAS;AAAA,EACnD,CAAA;AAAA,EACA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,CAAC,GAAA,MAAwB;AAAA,MACjC,IAAA,EAAM,iBAAA;AAAA,MACN,IAAA,EAAM,EAAE,GAAA;AAAI,KACd,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,GAAA,EAAa,MAAA,GAAS,QAAA,MAAqB;AAAA,MACnD,IAAA,EAAM,iBAAA;AAAA,MACN,IAAA,EAAM,EAAE,GAAA,EAAK,MAAA;AAAO,KACtB,CAAA;AAAA,IACA,IAAA,EAAM,CAAC,IAAA,MAAyB,EAAE,MAAM,aAAA,EAAe,IAAA,EAAM,EAAE,IAAA,EAAK,EAAE,CAAA;AAAA,IACtE,KAAA,EAAO,OAAc,EAAE,IAAA,EAAM,cAAA,EAAe,CAAA;AAAA,IAC5C,eAAA,EAAiB,CAAC,QAAA,MAA4B;AAAA,MAC5C,IAAA,EAAM,yBAAA;AAAA,MACN,IAAA,EAAM,EAAE,QAAA;AAAS,KACnB;AAAA;AAEJ;;;AC1KA,SAAS,QAAQ,GAAA,EAAwB;AACvC,EAAA,OAAO,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,OAAO,IAAI,IAAA,KAAS,QAAA;AAC/D;AAMO,IAAM,UAAN,MAA4B;AAAA,EAGjC,YAAY,MAAA,EAAwB;AAClC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,OAAc,IAAI,KAAA,EAAqC;AACrD,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,UAAA,EAAW;AAExC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,KAAA,EAAQ,KAAA,CAAM,KAAA,IAAS,EAAC;AAAA,MACxB,KAAA;AAAA,MACA,SAAA,EAAW,CAAA;AAAA,MACX,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,EAAA;AAAA,MACA,OAAA,EAAS,CAACA,MAAAA,KAAkB;AAC1B,QAAA,MAAMA,MAAAA,IAAS,EAAE,IAAA,EAAM,eAAA,EAAgB;AAAA,MACzC;AAAA,KACF;AAEA,IAAA,IAAI;AACF,MAAA,IAAI,UAAA,GAAgC,KAAA,CAAA;AAGpC,MAAA,KAAA,MAAWC,OAAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AAC9C,QAAA,IAAIA,QAAO,WAAA,EAAa;AACtB,UAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,QAAA;AAAA,YACzBA,OAAAA,CAAO,WAAA,CAAY,EAAE,KAAA,IAAS,OAAO,CAAA;AAAA,YACrC;AAAA,WACF;AACA,UAAA,IAAI,MAAA,EAAQ;AACV,YAAA,UAAA,GAAa,MAAA;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAGA,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,WAAA,EAAa;AAClC,QAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,QAAA;AAAA,UACzB,KAAK,MAAA,CAAO,KAAA,CAAM,YAAY,EAAE,KAAA,IAAS,OAAO,CAAA;AAAA,UAChD;AAAA,SACF;AACA,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,UAAA,GAAa,MAAA;AAAA,QACf;AAAA,MACF;AAOA,MAAA,IAAI,CAAC,UAAA,IAAc,KAAA,CAAM,UAAA,EAAY;AACnC,QAAA,UAAA,GAAa,KAAA,CAAM,UAAA;AAAA,MACrB;AAEA,MAAA,IAAI,CAAC,UAAA,IAAc,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO;AACpC,QAAA,UAAA,GAAa,OAAO,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,OAAO,CAAA;AAAA,MACzD;AAGA,MAAA,OAAO,UAAA,EAAY;AACjB,QAAA,IAAI,OAAA,CAAQ,SAAA,EAAA,KAAgB,IAAA,CAAK,MAAA,CAAO,kBAAkB,EAAA,CAAA,EAAK;AAC7D,UAAA,OAAO,IAAA,CAAK,IAAA;AAAA,YACV,EAAE,IAAA,EAAM,OAAA,EAAS,MAAM,EAAE,OAAA,EAAS,sBAAqB,EAAE;AAAA,YACzD;AAAA,WACF;AACA,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,OAAA,GAAsB,UAAA;AAC5B,QAAA,UAAA,GAAa,KAAA,CAAA;AAGb,QAAA,MAAM,aAAiC,OAAA,CAAQ,MAAA;AAE/C,QAAA,IAAI,CAAC,UAAA,EAAY;AACf,UAAA,OAAO,IAAA,CAAK,IAAA;AAAA,YACV;AAAA,cACE,IAAA,EAAM,OAAA;AAAA,cACN,IAAA,EAAM,EAAE,OAAA,EAAS,uCAAA;AAAwC,aAC3D;AAAA,YACA;AAAA,WACF;AACA,UAAA;AAAA,QACF;AAEA,QAAA,MAAMC,OAAAA,GAA8B,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAElE,QAAA,IAAI,CAACA,OAAAA,EAAQ;AACX,UAAA,OAAO,IAAA,CAAK,IAAA;AAAA,YACV;AAAA,cACE,IAAA,EAAM,OAAA;AAAA,cACN,IAAA,EAAM,EAAE,OAAA,EAAS,CAAA,OAAA,EAAU,UAAU,CAAA,UAAA,CAAA;AAAa,aACpD;AAAA,YACA;AAAA,WACF;AACA,UAAA;AAAA,QACF;AAGA,QAAA,MAAM,SAAS,OAAO,IAAA,CAAK,aAAA,CAAcA,OAAAA,EAAQ,SAAS,OAAO,CAAA;AAGjE,QAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AAGrB,UAAA,UAAA,GAAa,OAAO,IAAA,CAAK,eAAA;AAAA,YACvB;AAAA,cACE,IAAA,EAAM,eAAA;AAAA,cACN,IAAA,EAAM;AAAA,gBACJ,GAAG,OAAA;AAAA;AAAA,gBACH,MAAA,EAAQ,UAAA;AAAA,gBACR;AAAA;AACF,aACF;AAAA,YACA;AAAA,WACF;AAAA,QACF,CAAA,MAAO;AAEL,UAAA,UAAA,GAAa,MAAA;AAAA,QACf;AAAA,MACF;AAGA,MAAA,KAAA,MAAWD,OAAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AAC9C,QAAA,IAAIA,QAAO,UAAA,EAAY;AACrB,UAAA,OAAO,KAAK,QAAA,CAASA,OAAAA,CAAO,UAAA,CAAW,OAAO,GAAG,OAAO,CAAA;AAAA,QAC1D;AAAA,MACF;AAGA,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,UAAA,EAAY;AACjC,QAAA,OAAO,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA,CAAO,MAAM,UAAA,CAAW,OAAO,GAAG,OAAO,CAAA;AAAA,MACrE;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,WAAA;AAEJ,MAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClB,QAAA,WAAA,GAAc,KAAA;AAAA,MAChB,CAAA,MAAO;AAEL,QAAA,WAAA,GAAc;AAAA,UACZ,IAAA,EAAM,OAAA;AAAA,UACN,IAAA,EAAM;AAAA,YACJ,SAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,YAC9D,KAAA,EAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,KAAA,GAAQ;AAAA;AAChD,SACF;AAAA,MACF;AAEA,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,OAAO,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,OAAO,CAAA;AAAA,MACvC;AAEA,MAAA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe,eAAA,CACb,KAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,KAAA,CAAO,OAAO,OAAO,CAAA;AACnD,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,UAAU,IAAA,EAAK;AAC7C,MAAA,IAAI,MAAM,OAAO,KAAA;AACjB,MAAA,OAAO,IAAA,CAAK,IAAA,CAAK,KAAA,EAAgB,OAAO,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,OAAe,aAAA,CACbC,OAAAA,EACA,UAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,SAAS,UAAA,CAAW,MAAA;AAG1B,IAAA,KAAA,MAAWD,OAAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AAC9C,MAAA,IAAIA,QAAO,cAAA,EAAgB;AACzB,QAAA,MAAM,UAAA,GAAa,OAAO,IAAA,CAAK,QAAA;AAAA,UAC7BA,OAAAA,CAAO,eAAe,EAAE,MAAA,EAAAC,SAAQ,MAAA,EAAQ,UAAA,IAAc,OAAO,CAAA;AAAA,UAC7D;AAAA,SACF;AACA,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,UAAA,GAAa,UAAA;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,cAAA,EAAgB;AACrC,MAAA,MAAM,UAAA,GAAa,OAAO,IAAA,CAAK,QAAA;AAAA,QAC7B,IAAA,CAAK,OAAO,KAAA,CAAM,cAAA;AAAA,UAChB,EAAE,MAAA,EAAAA,OAAAA,EAAQ,MAAA,EAAQ,UAAA,EAAW;AAAA,UAC7B;AAAA,SACF;AAAA,QACA;AAAA,OACF;AACA,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,UAAA,GAAa,UAAA;AAAA,MACf;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAYA,OAAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAA;AAChD,MAAA,IAAI,MAAA;AAEJ,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,UAAU,IAAA,EAAK;AAC7C,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAA,GAAS,KAAA;AACT,UAAA;AAAA,QACF;AACA,QAAA,OAAO,IAAA,CAAK,IAAA,CAAK,KAAA,EAAgB,OAAO,CAAA;AAAA,MAC1C;AAGA,MAAA,KAAA,MAAWD,OAAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AAC9C,QAAA,IAAIA,QAAO,aAAA,EAAe;AACxB,UAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,QAAA;AAAA,YACxBA,OAAAA,CAAO,cAAc,EAAE,MAAA,EAAAC,SAAQ,IAAA,EAAM,MAAA,IAAU,OAAO,CAAA;AAAA,YACtD;AAAA,WACF;AACA,UAAA,IAAI,KAAA,EAAO;AACT,YAAA,UAAA,GAAa,KAAA;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAGA,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,aAAA,EAAe;AACpC,QAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,QAAA;AAAA,UACxB,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,aAAA,CAAc,EAAE,QAAAA,OAAAA,EAAQ,IAAA,EAAM,MAAA,EAAO,EAAG,OAAO,CAAA;AAAA,UACjE;AAAA,SACF;AACA,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,UAAA,GAAa,KAAA;AAAA,QACf;AAAA,MACF;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,EAAG,MAAM,KAAA;AAE1B,MAAA,MAAM;AAAA,QACJ,IAAA,EAAM,OAAA;AAAA,QACN,IAAA,EAAM;AAAA,UACJ,QAAQA,OAAAA,CAAO,IAAA;AAAA,UACf,SAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,UAC9D,KAAA,EAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,KAAA,GAAQ;AAAA;AAChD,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,QAAA,CACb,SAAA,EACA,OAAA,EACiC;AACjC,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,UAAU,IAAA,EAAK;AAC7C,MAAA,IAAI,MAAM,OAAO,KAAA;AACjB,MAAA,OAAO,IAAA,CAAK,IAAA,CAAK,KAAA,EAAgB,OAAO,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,IAAA,CACb,KAAA,EACA,OAAA,EACuB;AACvB,IAAA,MAAM,UAAA,GAAa;AAAA,MACjB,GAAG,KAAA;AAAA,MACH,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,SAAA,EAAW,KAAA,CAAM,SAAA,IAAa,IAAA,CAAK,GAAA,EAAI;AAAA,MACvC,IAAA,EAAM,MAAM,IAAA,IAAQ,WAAA;AAAA,MACpB,OAAO,OAAA,CAAQ;AAAA,KACjB;AAGA,IAAA,MAAM,UAAA;AAGN,IAAA,KAAA,MAAWD,OAAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,EAAC,EAAG;AAC9C,MAAA,IAAIA,QAAO,OAAA,EAAS;AAClB,QAAA,MAAM,SAAA,GAAYA,OAAAA,CAAO,OAAA,CAAQ,UAAA,EAAY,OAAO,CAAA;AACpD,QAAA,WAAA,MAAiB,SAAS,SAAA,EAAW;AACnC,UAAA,MAAM,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,QAAQ,KAAA,EAAO,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAE;AAAA,QAChE;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,OAAA,EAAS;AAC9B,MAAA,MAAM,YAAY,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,YAAY,OAAO,CAAA;AAC/D,MAAA,WAAA,MAAiB,SAAS,SAAA,EAAW;AAEnC,QAAA,MAAM,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,QAAQ,KAAA,EAAO,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAE;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,MAAA,GAAS,CAAe,MAAA,KAA2B;AAC9D,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAgB,MAAM,CAAA;AAC1C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,GAAA,EAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO;AAAA,GAC/B;AACF;AAKO,IAAM,MAAA,GAAS,CACpB,MAAA,KACsB;AAKjB,IAAM,MAAA,GAAS,CAAe,MAAA,KACnC","file":"chunk-EGZ4YTE4.js","sourcesContent":["import {\n UIColor,\n UIContract,\n UINode,\n UISize,\n Event,\n UISpacing,\n UIWidth,\n UIRadius,\n} 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: (\n props: UIContract[\"list\"] & { children: UINode<any>[] },\n ): 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"]}
|