forked from elizaOS/eliza
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontext.ts
104 lines (101 loc) · 4.17 KB
/
context.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import handlebars from "handlebars";
import { type State } from "./types.ts";
/**
* Composes a context string by replacing placeholders in a template with corresponding values from the state.
*
* This function takes a template string with placeholders in the format `{{placeholder}}` and a state object.
* It replaces each placeholder with the value from the state object that matches the placeholder's name.
* If a matching key is not found in the state object for a given placeholder, the placeholder is replaced with an empty string.
*
* By default, this function uses a simple string replacement approach. However, when `templatingEngine` is set to `'handlebars'`, it uses Handlebars templating engine instead, compiling the template into a reusable function and evaluating it with the provided state object.
*
* @param {Object} params - The parameters for composing the context.
* @param {State} params.state - The state object containing values to replace the placeholders in the template.
* @param {string} params.template - The template string containing placeholders to be replaced with state values.
* @param {"handlebars" | undefined} [params.templatingEngine] - The templating engine to use for compiling and evaluating the template (optional, default: `undefined`).
* @returns {string} The composed context string with placeholders replaced by corresponding state values.
*
* @example
* // Given a state object and a template
* const state = { userName: "Alice", userAge: 30 };
* const template = "Hello, {{userName}}! You are {{userAge}} years old";
*
* // Composing the context with simple string replacement will result in:
* // "Hello, Alice! You are 30 years old."
* const contextSimple = composeContext({ state, template });
*
* // Composing the context with Handlebars templating engine will also produce the same output.
* const contextHandlebars = composeContext({ state, template, templatingEngine: 'handlebars' });
*
* // Handlebars provides more advanced features than simple string replacement.
* // For example, you can use conditionals or loops right in your template:
* const advancedTemplate = `
* {{#if userAge}}
* Hello, {{userName}}! {{#if (gt userAge 18)}}You are an adult.{{else}}You are a minor.{{/if}}
* {{else}}
* Hello! We don't know your age.
* {{/if}}
*
* {{#each favoriteColors}}
* - Your favorite color: {{this}}
* {{/each}}
* `;
*
* const advancedState = {
* userName: "Alice",
* userAge: 30,
* favoriteColors: ["blue", "green", "red"]
* };
*
* // Using Handlebars with the more advanced template:
* const advancedContextHandlebars = composeContext({ state: advancedState, template: advancedTemplate, templatingEngine: 'handlebars' });
*
* // The above will produce:
* // "Hello, Alice! You are an adult.
* //
* // - Your favorite color: blue
* // - Your favorite color: green
* // - Your favorite color: red"
*/
export const composeContext = ({
state,
template,
templatingEngine,
}: {
state: State;
template: string;
templatingEngine?: "handlebars";
}) => {
if (templatingEngine === "handlebars") {
const templateFunction = handlebars.compile(template);
return templateFunction(state);
}
// @ts-expect-error match isn't working as expected
const out = template.replace(/{{\w+}}/g, (match) => {
const key = match.replace(/{{|}}/g, "");
return state[key] ?? "";
});
return out;
};
/**
* Adds a header to a body of text.
*
* This function takes a header string and a body string and returns a new string with the header prepended to the body.
* If the body string is empty, the header is returned as is.
*
* @param {string} header - The header to add to the body.
* @param {string} body - The body to which to add the header.
* @returns {string} The body with the header prepended.
*
* @example
* // Given a header and a body
* const header = "Header";
* const body = "Body";
*
* // Adding the header to the body will result in:
* // "Header\nBody"
* const text = addHeader(header, body);
*/
export const addHeader = (header: string, body: string) => {
return body.length > 0 ? `${header ? header + "\n" : header}${body}\n` : "";
};