@sprucelabs/sprucebot-llm 15.1.11 → 15.1.12
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/build/bots/adapters/MessageBuilder.d.ts +1 -0
- package/build/bots/adapters/MessageBuilder.js +9 -0
- package/build/esm/bots/adapters/MessageBuilder.d.ts +1 -0
- package/build/esm/bots/adapters/MessageBuilder.js +9 -0
- package/build/esm/parsingResponses/ResponseParserV2.js +19 -22
- package/build/parsingResponses/ResponseParserV2.js +19 -22
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ export default class MessageBuilder {
|
|
|
13
13
|
private shouldRememberImages;
|
|
14
14
|
private buildFirstMessage;
|
|
15
15
|
private buildSkillMessages;
|
|
16
|
+
private buildFunctionSyntaxMessage;
|
|
16
17
|
private buildCallbacksMessage;
|
|
17
18
|
private buildPleaseKeepInMindMessage;
|
|
18
19
|
private buildStateMessage;
|
|
@@ -102,6 +102,9 @@ class MessageBuilder {
|
|
|
102
102
|
}
|
|
103
103
|
const messages = [];
|
|
104
104
|
messages.push(this.buildYourJobMessage(skill.yourJobIfYouChooseToAcceptItIs));
|
|
105
|
+
if (skill.callbacks || skill.state || skill.stateSchema) {
|
|
106
|
+
messages.push(this.buildFunctionSyntaxMessage());
|
|
107
|
+
}
|
|
105
108
|
if (skill.stateSchema) {
|
|
106
109
|
messages.push(this.buildStateSchemaMessage(skill.stateSchema));
|
|
107
110
|
}
|
|
@@ -120,6 +123,12 @@ class MessageBuilder {
|
|
|
120
123
|
}
|
|
121
124
|
return messages;
|
|
122
125
|
}
|
|
126
|
+
buildFunctionSyntaxMessage() {
|
|
127
|
+
return {
|
|
128
|
+
role: 'system',
|
|
129
|
+
content: `Throughout this conversation, all function calls and state updates use JavaScript-style syntax: @functionName({ "key": "value" }). The function name follows the @ symbol, and the single argument is a JSON object wrapped in parentheses. All JSON must be on a single line.`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
123
132
|
buildCallbacksMessage(callbacks) {
|
|
124
133
|
const keys = Object.keys(callbacks);
|
|
125
134
|
const descriptions = [];
|
|
@@ -13,6 +13,7 @@ export default class MessageBuilder {
|
|
|
13
13
|
private shouldRememberImages;
|
|
14
14
|
private buildFirstMessage;
|
|
15
15
|
private buildSkillMessages;
|
|
16
|
+
private buildFunctionSyntaxMessage;
|
|
16
17
|
private buildCallbacksMessage;
|
|
17
18
|
private buildPleaseKeepInMindMessage;
|
|
18
19
|
private buildStateMessage;
|
|
@@ -98,6 +98,9 @@ export default class MessageBuilder {
|
|
|
98
98
|
}
|
|
99
99
|
const messages = [];
|
|
100
100
|
messages.push(this.buildYourJobMessage(skill.yourJobIfYouChooseToAcceptItIs));
|
|
101
|
+
if (skill.callbacks || skill.state || skill.stateSchema) {
|
|
102
|
+
messages.push(this.buildFunctionSyntaxMessage());
|
|
103
|
+
}
|
|
101
104
|
if (skill.stateSchema) {
|
|
102
105
|
messages.push(this.buildStateSchemaMessage(skill.stateSchema));
|
|
103
106
|
}
|
|
@@ -116,6 +119,12 @@ export default class MessageBuilder {
|
|
|
116
119
|
}
|
|
117
120
|
return messages;
|
|
118
121
|
}
|
|
122
|
+
buildFunctionSyntaxMessage() {
|
|
123
|
+
return {
|
|
124
|
+
role: 'system',
|
|
125
|
+
content: `Throughout this conversation, all function calls and state updates use JavaScript-style syntax: @functionName({ "key": "value" }). The function name follows the @ symbol, and the single argument is a JSON object wrapped in parentheses. All JSON must be on a single line.`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
119
128
|
buildCallbacksMessage(callbacks) {
|
|
120
129
|
const keys = Object.keys(callbacks);
|
|
121
130
|
const descriptions = [];
|
|
@@ -15,9 +15,8 @@ export default class ResponseParserV2 {
|
|
|
15
15
|
let message = response.replace(DONE_TOKEN, '').trim();
|
|
16
16
|
let state = undefined;
|
|
17
17
|
let callbackResults = undefined;
|
|
18
|
-
const hasCallbacks =
|
|
19
|
-
(callbacks
|
|
20
|
-
Object.keys(callbacks).some((name) => message.includes(`@${name}`)));
|
|
18
|
+
const hasCallbacks = callbacks != null &&
|
|
19
|
+
Object.keys(callbacks).some((name) => message.includes(`@${name}(`));
|
|
21
20
|
if (hasCallbacks) {
|
|
22
21
|
const { callbackResults: c, message: m } = yield this.invokeCallbacks(message, callbacks);
|
|
23
22
|
callbackResults = c;
|
|
@@ -26,7 +25,7 @@ export default class ResponseParserV2 {
|
|
|
26
25
|
const hasState = response.includes('@updateState');
|
|
27
26
|
if (hasState && message) {
|
|
28
27
|
const stateMatches = [
|
|
29
|
-
...message.matchAll(/@updateState\
|
|
28
|
+
...message.matchAll(/@updateState\(({[\s\S]*?})\)\n?/g),
|
|
30
29
|
];
|
|
31
30
|
for (const stateMatch of stateMatches) {
|
|
32
31
|
try {
|
|
@@ -57,17 +56,16 @@ export default class ResponseParserV2 {
|
|
|
57
56
|
let callbackStrippedMessage = message;
|
|
58
57
|
let callbackResults = '';
|
|
59
58
|
const reserved = new Set(['updateState', 'results']);
|
|
60
|
-
const matches = [...message.matchAll(/^@(\w+)\
|
|
59
|
+
const matches = [...message.matchAll(/^@(\w+)\(({.*})\)$/gm)];
|
|
61
60
|
for (const match of matches) {
|
|
62
61
|
if (reserved.has(match[1])) {
|
|
63
62
|
continue;
|
|
64
63
|
}
|
|
65
64
|
const parsed = JSON.parse(match[2]);
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const options = isCanonical ? parsed.options : parsed;
|
|
65
|
+
const name = match[1];
|
|
66
|
+
const options = parsed;
|
|
69
67
|
const callback = callbacks === null || callbacks === void 0 ? void 0 : callbacks[name];
|
|
70
|
-
if (!
|
|
68
|
+
if (!callback) {
|
|
71
69
|
continue;
|
|
72
70
|
}
|
|
73
71
|
const parts = callbackStrippedMessage.split(match[0]);
|
|
@@ -103,32 +101,31 @@ export default class ResponseParserV2 {
|
|
|
103
101
|
}
|
|
104
102
|
getStateUpdateInstructions() {
|
|
105
103
|
return `Updating state works similar to all function calls. Use the following syntax:
|
|
106
|
-
@updateState
|
|
104
|
+
@updateState({ "field1": "value1", "field2": "value2" })
|
|
107
105
|
Make sure to json encode only the fields you want to change. You can update state once and do it at the end of any messages you send. IMPORTANT: JSON must be on a single line. Do NOT use multi-line or formatted JSON.
|
|
108
106
|
Your user-facing message is always sent to the user, even if @updateState fails. If @updateState fails later, do not repeat the same message. Only send the specific @updateState needed to fix the missing state change.
|
|
109
107
|
Good example:
|
|
110
|
-
@updateState
|
|
108
|
+
@updateState({ "favoriteColor": "blue", "firstName": "Taylor" })
|
|
111
109
|
Bad examples:
|
|
112
110
|
@updateState
|
|
113
111
|
{ "favoriteColor": "blue" }
|
|
114
|
-
@updateState
|
|
112
|
+
@updateState({
|
|
115
113
|
"favoriteColor": "blue"
|
|
116
|
-
}
|
|
117
|
-
@updateState
|
|
114
|
+
})
|
|
115
|
+
@updateState({ favoriteColor: "blue" })`;
|
|
118
116
|
}
|
|
119
117
|
getFunctionCallInstructions() {
|
|
120
118
|
return `A function call is done using the following syntax:
|
|
121
|
-
@
|
|
122
|
-
Make sure to json encode the options
|
|
119
|
+
@callbackName({ "key": "value" })
|
|
120
|
+
Make sure to json encode the options. You can call as many callbacks as you want in a single response by including multiple @functionName() lines. IMPORTANT: JSON must be on a single line. Do NOT use multi-line or formatted JSON.
|
|
123
121
|
Your user-facing message is always sent to the user, even if a callback fails. Successful callbacks have already run successfully. If a callback fails later, do not repeat the same message and do not repeat successful callbacks. Only call the specific callback needed to fix the failed gap.
|
|
124
122
|
Good example:
|
|
125
|
-
@
|
|
123
|
+
@lookupWeather({ "zip": "80524" })
|
|
126
124
|
Bad examples:
|
|
127
125
|
@lookupWeather { "zip": "80524" }
|
|
128
|
-
@
|
|
129
|
-
{ "
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
} }`;
|
|
126
|
+
@lookupWeather(
|
|
127
|
+
{ "zip": "80524" }
|
|
128
|
+
)
|
|
129
|
+
@lookupWeather({ zip: "80524" })`;
|
|
133
130
|
}
|
|
134
131
|
}
|
|
@@ -10,9 +10,8 @@ class ResponseParserV2 {
|
|
|
10
10
|
let message = response.replace(templates_1.DONE_TOKEN, '').trim();
|
|
11
11
|
let state = undefined;
|
|
12
12
|
let callbackResults = undefined;
|
|
13
|
-
const hasCallbacks =
|
|
14
|
-
(callbacks
|
|
15
|
-
Object.keys(callbacks).some((name) => message.includes(`@${name}`)));
|
|
13
|
+
const hasCallbacks = callbacks != null &&
|
|
14
|
+
Object.keys(callbacks).some((name) => message.includes(`@${name}(`));
|
|
16
15
|
if (hasCallbacks) {
|
|
17
16
|
const { callbackResults: c, message: m } = await this.invokeCallbacks(message, callbacks);
|
|
18
17
|
callbackResults = c;
|
|
@@ -21,7 +20,7 @@ class ResponseParserV2 {
|
|
|
21
20
|
const hasState = response.includes('@updateState');
|
|
22
21
|
if (hasState && message) {
|
|
23
22
|
const stateMatches = [
|
|
24
|
-
...message.matchAll(/@updateState\
|
|
23
|
+
...message.matchAll(/@updateState\(({[\s\S]*?})\)\n?/g),
|
|
25
24
|
];
|
|
26
25
|
for (const stateMatch of stateMatches) {
|
|
27
26
|
try {
|
|
@@ -50,17 +49,16 @@ class ResponseParserV2 {
|
|
|
50
49
|
let callbackStrippedMessage = message;
|
|
51
50
|
let callbackResults = '';
|
|
52
51
|
const reserved = new Set(['updateState', 'results']);
|
|
53
|
-
const matches = [...message.matchAll(/^@(\w+)\
|
|
52
|
+
const matches = [...message.matchAll(/^@(\w+)\(({.*})\)$/gm)];
|
|
54
53
|
for (const match of matches) {
|
|
55
54
|
if (reserved.has(match[1])) {
|
|
56
55
|
continue;
|
|
57
56
|
}
|
|
58
57
|
const parsed = JSON.parse(match[2]);
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const options = isCanonical ? parsed.options : parsed;
|
|
58
|
+
const name = match[1];
|
|
59
|
+
const options = parsed;
|
|
62
60
|
const callback = callbacks?.[name];
|
|
63
|
-
if (!
|
|
61
|
+
if (!callback) {
|
|
64
62
|
continue;
|
|
65
63
|
}
|
|
66
64
|
const parts = callbackStrippedMessage.split(match[0]);
|
|
@@ -95,33 +93,32 @@ class ResponseParserV2 {
|
|
|
95
93
|
}
|
|
96
94
|
getStateUpdateInstructions() {
|
|
97
95
|
return `Updating state works similar to all function calls. Use the following syntax:
|
|
98
|
-
@updateState
|
|
96
|
+
@updateState({ "field1": "value1", "field2": "value2" })
|
|
99
97
|
Make sure to json encode only the fields you want to change. You can update state once and do it at the end of any messages you send. IMPORTANT: JSON must be on a single line. Do NOT use multi-line or formatted JSON.
|
|
100
98
|
Your user-facing message is always sent to the user, even if @updateState fails. If @updateState fails later, do not repeat the same message. Only send the specific @updateState needed to fix the missing state change.
|
|
101
99
|
Good example:
|
|
102
|
-
@updateState
|
|
100
|
+
@updateState({ "favoriteColor": "blue", "firstName": "Taylor" })
|
|
103
101
|
Bad examples:
|
|
104
102
|
@updateState
|
|
105
103
|
{ "favoriteColor": "blue" }
|
|
106
|
-
@updateState
|
|
104
|
+
@updateState({
|
|
107
105
|
"favoriteColor": "blue"
|
|
108
|
-
}
|
|
109
|
-
@updateState
|
|
106
|
+
})
|
|
107
|
+
@updateState({ favoriteColor: "blue" })`;
|
|
110
108
|
}
|
|
111
109
|
getFunctionCallInstructions() {
|
|
112
110
|
return `A function call is done using the following syntax:
|
|
113
|
-
@
|
|
114
|
-
Make sure to json encode the options
|
|
111
|
+
@callbackName({ "key": "value" })
|
|
112
|
+
Make sure to json encode the options. You can call as many callbacks as you want in a single response by including multiple @functionName() lines. IMPORTANT: JSON must be on a single line. Do NOT use multi-line or formatted JSON.
|
|
115
113
|
Your user-facing message is always sent to the user, even if a callback fails. Successful callbacks have already run successfully. If a callback fails later, do not repeat the same message and do not repeat successful callbacks. Only call the specific callback needed to fix the failed gap.
|
|
116
114
|
Good example:
|
|
117
|
-
@
|
|
115
|
+
@lookupWeather({ "zip": "80524" })
|
|
118
116
|
Bad examples:
|
|
119
117
|
@lookupWeather { "zip": "80524" }
|
|
120
|
-
@
|
|
121
|
-
{ "
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
} }`;
|
|
118
|
+
@lookupWeather(
|
|
119
|
+
{ "zip": "80524" }
|
|
120
|
+
)
|
|
121
|
+
@lookupWeather({ zip: "80524" })`;
|
|
125
122
|
}
|
|
126
123
|
}
|
|
127
124
|
exports.default = ResponseParserV2;
|