@sprucelabs/sprucebot-llm 15.1.10 → 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 +22 -23
- package/build/parsingResponses/ResponseParserV2.js +22 -23
- 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;
|
|
@@ -25,8 +24,10 @@ export default class ResponseParserV2 {
|
|
|
25
24
|
}
|
|
26
25
|
const hasState = response.includes('@updateState');
|
|
27
26
|
if (hasState && message) {
|
|
28
|
-
const
|
|
29
|
-
|
|
27
|
+
const stateMatches = [
|
|
28
|
+
...message.matchAll(/@updateState\(({[\s\S]*?})\)\n?/g),
|
|
29
|
+
];
|
|
30
|
+
for (const stateMatch of stateMatches) {
|
|
30
31
|
try {
|
|
31
32
|
state = JSON.parse(stateMatch[1]);
|
|
32
33
|
}
|
|
@@ -55,17 +56,16 @@ export default class ResponseParserV2 {
|
|
|
55
56
|
let callbackStrippedMessage = message;
|
|
56
57
|
let callbackResults = '';
|
|
57
58
|
const reserved = new Set(['updateState', 'results']);
|
|
58
|
-
const matches = [...message.matchAll(/^@(\w+)\
|
|
59
|
+
const matches = [...message.matchAll(/^@(\w+)\(({.*})\)$/gm)];
|
|
59
60
|
for (const match of matches) {
|
|
60
61
|
if (reserved.has(match[1])) {
|
|
61
62
|
continue;
|
|
62
63
|
}
|
|
63
64
|
const parsed = JSON.parse(match[2]);
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
const options = isCanonical ? parsed.options : parsed;
|
|
65
|
+
const name = match[1];
|
|
66
|
+
const options = parsed;
|
|
67
67
|
const callback = callbacks === null || callbacks === void 0 ? void 0 : callbacks[name];
|
|
68
|
-
if (!
|
|
68
|
+
if (!callback) {
|
|
69
69
|
continue;
|
|
70
70
|
}
|
|
71
71
|
const parts = callbackStrippedMessage.split(match[0]);
|
|
@@ -101,32 +101,31 @@ export default class ResponseParserV2 {
|
|
|
101
101
|
}
|
|
102
102
|
getStateUpdateInstructions() {
|
|
103
103
|
return `Updating state works similar to all function calls. Use the following syntax:
|
|
104
|
-
@updateState
|
|
104
|
+
@updateState({ "field1": "value1", "field2": "value2" })
|
|
105
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.
|
|
106
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.
|
|
107
107
|
Good example:
|
|
108
|
-
@updateState
|
|
108
|
+
@updateState({ "favoriteColor": "blue", "firstName": "Taylor" })
|
|
109
109
|
Bad examples:
|
|
110
110
|
@updateState
|
|
111
111
|
{ "favoriteColor": "blue" }
|
|
112
|
-
@updateState
|
|
112
|
+
@updateState({
|
|
113
113
|
"favoriteColor": "blue"
|
|
114
|
-
}
|
|
115
|
-
@updateState
|
|
114
|
+
})
|
|
115
|
+
@updateState({ favoriteColor: "blue" })`;
|
|
116
116
|
}
|
|
117
117
|
getFunctionCallInstructions() {
|
|
118
118
|
return `A function call is done using the following syntax:
|
|
119
|
-
@
|
|
120
|
-
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.
|
|
121
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.
|
|
122
122
|
Good example:
|
|
123
|
-
@
|
|
123
|
+
@lookupWeather({ "zip": "80524" })
|
|
124
124
|
Bad examples:
|
|
125
125
|
@lookupWeather { "zip": "80524" }
|
|
126
|
-
@
|
|
127
|
-
{ "
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
} }`;
|
|
126
|
+
@lookupWeather(
|
|
127
|
+
{ "zip": "80524" }
|
|
128
|
+
)
|
|
129
|
+
@lookupWeather({ zip: "80524" })`;
|
|
131
130
|
}
|
|
132
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;
|
|
@@ -20,8 +19,10 @@ class ResponseParserV2 {
|
|
|
20
19
|
}
|
|
21
20
|
const hasState = response.includes('@updateState');
|
|
22
21
|
if (hasState && message) {
|
|
23
|
-
const
|
|
24
|
-
|
|
22
|
+
const stateMatches = [
|
|
23
|
+
...message.matchAll(/@updateState\(({[\s\S]*?})\)\n?/g),
|
|
24
|
+
];
|
|
25
|
+
for (const stateMatch of stateMatches) {
|
|
25
26
|
try {
|
|
26
27
|
state = JSON.parse(stateMatch[1]);
|
|
27
28
|
}
|
|
@@ -48,17 +49,16 @@ class ResponseParserV2 {
|
|
|
48
49
|
let callbackStrippedMessage = message;
|
|
49
50
|
let callbackResults = '';
|
|
50
51
|
const reserved = new Set(['updateState', 'results']);
|
|
51
|
-
const matches = [...message.matchAll(/^@(\w+)\
|
|
52
|
+
const matches = [...message.matchAll(/^@(\w+)\(({.*})\)$/gm)];
|
|
52
53
|
for (const match of matches) {
|
|
53
54
|
if (reserved.has(match[1])) {
|
|
54
55
|
continue;
|
|
55
56
|
}
|
|
56
57
|
const parsed = JSON.parse(match[2]);
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const options = isCanonical ? parsed.options : parsed;
|
|
58
|
+
const name = match[1];
|
|
59
|
+
const options = parsed;
|
|
60
60
|
const callback = callbacks?.[name];
|
|
61
|
-
if (!
|
|
61
|
+
if (!callback) {
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
64
|
const parts = callbackStrippedMessage.split(match[0]);
|
|
@@ -93,33 +93,32 @@ class ResponseParserV2 {
|
|
|
93
93
|
}
|
|
94
94
|
getStateUpdateInstructions() {
|
|
95
95
|
return `Updating state works similar to all function calls. Use the following syntax:
|
|
96
|
-
@updateState
|
|
96
|
+
@updateState({ "field1": "value1", "field2": "value2" })
|
|
97
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.
|
|
98
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.
|
|
99
99
|
Good example:
|
|
100
|
-
@updateState
|
|
100
|
+
@updateState({ "favoriteColor": "blue", "firstName": "Taylor" })
|
|
101
101
|
Bad examples:
|
|
102
102
|
@updateState
|
|
103
103
|
{ "favoriteColor": "blue" }
|
|
104
|
-
@updateState
|
|
104
|
+
@updateState({
|
|
105
105
|
"favoriteColor": "blue"
|
|
106
|
-
}
|
|
107
|
-
@updateState
|
|
106
|
+
})
|
|
107
|
+
@updateState({ favoriteColor: "blue" })`;
|
|
108
108
|
}
|
|
109
109
|
getFunctionCallInstructions() {
|
|
110
110
|
return `A function call is done using the following syntax:
|
|
111
|
-
@
|
|
112
|
-
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.
|
|
113
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.
|
|
114
114
|
Good example:
|
|
115
|
-
@
|
|
115
|
+
@lookupWeather({ "zip": "80524" })
|
|
116
116
|
Bad examples:
|
|
117
117
|
@lookupWeather { "zip": "80524" }
|
|
118
|
-
@
|
|
119
|
-
{ "
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} }`;
|
|
118
|
+
@lookupWeather(
|
|
119
|
+
{ "zip": "80524" }
|
|
120
|
+
)
|
|
121
|
+
@lookupWeather({ zip: "80524" })`;
|
|
123
122
|
}
|
|
124
123
|
}
|
|
125
124
|
exports.default = ResponseParserV2;
|